<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>RubyGreenBlue::Blog ruby</title>
    <link>http://blog.rubygreenblue.com/</link>
    <pubDate>Sun Mar 09 09:37:36 +1100 2008</pubDate>
    <description>RubyGreenBlue::Blog</description>
    <item>
      <title>What are Ruby Symbols</title>
      <link>http://blog.rubygreenblue.com/blog/article/what_are_ruby_symbols</link>
      <description>&lt;p&gt;One of the hardest things to explain about Ruby (especially to newcomers) is what symbols are. Many explanations of symbols that I see or hear often only cover a low-level/technical difference between symbols and strings. That is, that symbols use one memory location for each unique instance whereas strings use separate memory locations for each instance. Also that symbols are kept around in memory for the life of the program while strings get cleaned up when they are no longer used.&lt;/p&gt;

&lt;p&gt;While these differences are accurate, they are just implementation details and not &lt;em&gt;really&lt;/em&gt; what Ruby symbols are all about and those who quote only these differences by way of explanation of what Ruby symbols are, are missing the point.&lt;/p&gt;

&lt;p&gt;What Ruby symbols are really about is beauty and semantics. Ruby symbols give the programmer the distinction between &lt;em&gt;identity&lt;/em&gt; and &lt;em&gt;information&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Consider this method call:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="ident"&gt;validates_presence_of&lt;/span&gt; &lt;span class="symbol"&gt;:firstname&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:lastname&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:on&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:create&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:message&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;can't be blank&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;and if we single out &lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="symbol"&gt;:message&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;can't be blank&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;&lt;code&gt;:message&lt;/code&gt; is a symbol and &lt;code&gt;"can't be blank"&lt;/code&gt; is a string. We could have easily written this statement like:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;can't be blank&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;But the difference here is that &lt;code&gt;:message&lt;/code&gt; is just a label for something, some concept, that a part of our program needs to work with. Whereas &lt;code&gt;"can't be blank"&lt;/code&gt; is actual &lt;em&gt;data&lt;/em&gt; or information. Another way to look at it is that we could mess with one of the two and the program would not care but if we mess with the other and the program &lt;em&gt;does&lt;/em&gt; care.&lt;/p&gt;

&lt;p&gt;If I change it to:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="symbol"&gt;:my_message&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;can't be blank&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;The program no longer works as it did before. The method does not look for anything labeled &lt;code&gt;:my_message&lt;/code&gt;. It is not a &lt;em&gt;concept&lt;/em&gt; it knows about. The label &lt;code&gt;:message&lt;/code&gt; is there only so the programmer and the method can talk about the same concept.&lt;/p&gt;

&lt;p&gt;Now if I change it to:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="symbol"&gt;:message&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;can't be blank, sorry about that.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="symbol"&gt;:message&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;darf nicht leer sein&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;The program still works as it did before, it just displays a different message. The &lt;code&gt;"can't be blank, sorry about that."&lt;/code&gt; is clearly different to &lt;code&gt;:message&lt;/code&gt;. It's not a label or an identity at all, it's information.&lt;/p&gt;

&lt;p&gt;Many other languages don't have this distinction between information and identity, or at least not in such a nice, convenient way. As a result, strings are often used to perform the task of labeling.&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="global"&gt;$car&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;array&lt;/span&gt; &lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;weight&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;=&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;1000&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;unit_of_measure&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;=&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;kg&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;year&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;=&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;2004&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;price&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;=&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;7000&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;);&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;If the program knows about the concept of &lt;code&gt;weight&lt;/code&gt; and &lt;code&gt;unit_of_measure&lt;/code&gt;, using strings for those labels doesn't quite feel right.&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="ident"&gt;car&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;&lt;span class="symbol"&gt;:weight&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1000&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:unit_of_measure&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;kg&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:year&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;2004&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:price&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;7000&lt;/span&gt;&lt;span class="punct"&gt;'}&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;Now we have a separation between the concepts our program deals with and the associated data. And with syntax highlighting it reads so much nicer.&lt;/p&gt;

&lt;p&gt;Take this example again&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="ident"&gt;validates_presence_of&lt;/span&gt; &lt;span class="symbol"&gt;:firstname&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:lastname&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:on&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:create&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:message&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;can't be blank&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;It reads so much nicer and is easier to see which bits, if changed, will affect the semantics of the program and which bits won't, but if we use strings for our labels, we lose that distinction.&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="ident"&gt;validates_presence_of&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;firstname&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;lastname&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;on&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;create&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;can't be blank&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;An easy way to work out if you should use a symbol or a string is this: Does the program care about the thing I am typing, or does the user care about it?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;if the program cares: &lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="symbol"&gt;:symbol&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if the user cares: &lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;string&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Sun Mar 09 09:37:36 +1100 2008</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/what_are_ruby_symbols</guid>
      <author>keith</author>
    </item>
    <item>
      <title>Finding Descendants of a Class</title>
      <link>http://blog.rubygreenblue.com/blog/article/class_descendants</link>
      <description>&lt;p&gt;Ruby offers a method for finding all the ancestors of a class (&lt;code&gt;ancestors&lt;/code&gt; funnily enough) but, as far as I know, no easy way to get at all the descendants of a class.&lt;/p&gt;

&lt;p&gt;I thought it had to be possible, this *is* Ruby after all! But in thinking about it a little more, I figured it could well be a tricky thing to do and probably require some hook in the Ruby language for it all to be even possible. &lt;/p&gt;

&lt;p&gt;Luckily I found this beauty: &lt;code&gt;ObjectSpace&lt;/code&gt;. With &lt;code&gt;ObjectSpace&lt;/code&gt; you can eacherate over every object in the Ruby object space. What else?&lt;/p&gt;

&lt;p&gt;So it tuns out that finding all the descendants of a particular class is not such a big deal after all. Just eacherate over &lt;code&gt;ObjectSpace&lt;/code&gt; and do a little recursion:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Object&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.show_descendants&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;klass&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;indent_level&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;klass&lt;/span&gt;
      &lt;span class="ident"&gt;klass&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;
      &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt; - &lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;indent_level&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;klass&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="constant"&gt;ObjectSpace&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_object&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;==&lt;/span&gt; &lt;span class="ident"&gt;Class&lt;/span&gt; &lt;span class="ident"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;superclass&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="ident"&gt;klass&lt;/span&gt;
        &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt; - &lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;indent_level&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
        &lt;span class="ident"&gt;show_descendants&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;indent_level&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;show_descendants&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;klass&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;indent_level&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;klass&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;show_descendants&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;indent_level&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;


&lt;span class="comment"&gt;# you can pass the class as an argument&lt;/span&gt;
&lt;span class="ident"&gt;show_descendants&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;ScriptError&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="comment"&gt;# or you can send the method to the class&lt;/span&gt;
&lt;span class="constant"&gt;Numeric&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;show_descendants&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;This code could be modified a little to return a list of descendants, each containing their own list of descendants rather than &lt;code&gt;puts&lt;/code&gt;ing it all to the screen.&lt;/p&gt;</description>
      <pubDate>Thu Dec 14 15:13:26 +1100 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/class_descendants</guid>
      <author>keith</author>
    </item>
    <item>
      <title>Enumerable Constants for Active Record Models</title>
      <link>http://blog.rubygreenblue.com/blog/article/enumerable_constants</link>
      <description>&lt;p&gt;A problem that had often bothered me in the past is this:&lt;/p&gt;

&lt;p&gt;You're modelling a concept in a database like, say, property listings and a property has an attribute of "type". The possible values of "type" are not arbitrary. They are some fixed set of values like "rental", "for sale" and "auction", and the software needs to do stuff depending on the value of "type".&lt;/p&gt;

&lt;p&gt;So this is like a &lt;code&gt;:belongs_to&lt;/code&gt; where a property belongs to a suburb say. But there is an important difference. With a &lt;code&gt;belongs_to :suburb&lt;/code&gt; the values for suburb &lt;em&gt;are&lt;/em&gt; arbitrary. That is to say that the software doesn't care about the values, only that there is some value (which the user cares about, of course). But the program &lt;em&gt;does&lt;/em&gt; care about the set of values available for the "type" attribute.&lt;/p&gt;

&lt;p&gt;Setting up a &lt;code&gt;has_many&lt;/code&gt;/&lt;code&gt;belongs_to&lt;/code&gt; relationship always seemed overkill but it gave me a nice list of available attributes and I could enforce the relationship. The other problem was that the data in the table would mirror some set of constants in the code. If you changed one, you had to make sure you changed the other or things got out of whack. Not to mention problems of populating a new database and making sure all such "non-arbitrary" value set tables had the correct values (including correct ids to match the constants in code) in them.&lt;/p&gt;

&lt;p&gt;Making the attribute "type" a string and stuffing values "rental", "for sale" and "auction" in it felt particularly bad. &lt;/p&gt;

&lt;h2&gt;Solution&lt;/h2&gt;

&lt;p&gt;I felt the correct way to do it was to use integer values in the field and represent these values as constants in the code (which is where the values have meaning).&lt;/p&gt;

&lt;p&gt;But writing validation for these and coming up with a list of human readable descriptions (for drop-downs) was tedious. It felt like the values belonged in the database... but wait, no, the values have meaning in the code...&lt;/p&gt;

&lt;p&gt;So I've written a Rails plugin to take away the tediousness of it all and make it a lot more DRY. With it I get &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an easy way to define, in a nice DSL looking way, what the constants are&lt;/li&gt;
&lt;li&gt;validation code generated dynamically&lt;/li&gt;
&lt;li&gt;a nice way of getting the list of values and descriptions (useful for UI stuff)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Examples&lt;/h2&gt;

&lt;p&gt;Model definition:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Property&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
  &lt;span class="ident"&gt;enumerable_constant&lt;/span&gt; &lt;span class="symbol"&gt;:type&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:constants&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:rental&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:for_sale&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:auction&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;Some view code:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;p&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;label&lt;/span&gt; &lt;span class="keyword"&gt;for&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;property_type&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class="constant"&gt;Property&lt;/span&gt; &lt;span class="constant"&gt;Type&lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;label&amp;gt;&amp;lt;br&lt;/span&gt;&lt;span class="punct"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;%=&lt;/span&gt;&lt;span class="string"&gt; collection_select(:property, :type, Property::Type.constants, :id, :title, {:prompt &lt;/span&gt;&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Select a Property Type&lt;/span&gt;&lt;span class="punct"&gt;'})&lt;/span&gt;  &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;br&lt;/span&gt; &lt;span class="punct"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;Note the use of &lt;code&gt;Property::Type.constants&lt;/code&gt; in place of where you would normally use a collection object like &lt;code&gt;@suburbs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Some code that tests the value&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="ident"&gt;property&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Property&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt; &lt;span class="symbol"&gt;:first&lt;/span&gt;
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;property&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="constant"&gt;Property&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Type&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;FOR_SALE&lt;/span&gt;
  &lt;span class="comment"&gt;# do some stuff&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;Other things you can access&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="punct"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;Property&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Type&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;constants&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;RENTAL&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;Property&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Type&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;constants&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Rental&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;Property&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Type&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;constants&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;Download the &lt;a href="http://rubygreenblue.com/project/enumerable_constants"&gt;Enumerable Constants project&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun Dec 10 18:44:16 +1100 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/enumerable_constants</guid>
      <author>keith</author>
    </item>
    <item>
      <title>Rails Workshop - Sydney</title>
      <link>http://blog.rubygreenblue.com/blog/article/rails_workshop</link>
      <description>&lt;p&gt;Last weekend I attended a Rails Workshop in Sydney. The workshop was put together by &lt;a href="http://wwworkshop.com.au/"&gt;wwworkshops&lt;/a&gt; and presented by &lt;a href="http://geoffreygrosenbach.com/"&gt;Geoffrey Grosenbach&lt;/a&gt; of &lt;a href="http://topfunky.com"&gt;Top Funky Corp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The workshop was great and I got a lot out of it. Geoffrey gave us a lot of material to wade thru and learn from including code (lots of code), screencasts and cheatsheets.&lt;/p&gt;

&lt;p&gt;Geoff is a great presenter. Although Geoff knows a ridiculous amount of stuff, he always comes across as being very approachable willing to learn from those he's presenting to. I like his style.&lt;/p&gt;

&lt;p&gt;It was also great to meet up with some talented people in the Sydney Rails community.&lt;/p&gt;</description>
      <pubDate>Fri Nov 24 10:50:35 +1100 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/rails_workshop</guid>
      <author>keith</author>
    </item>
    <item>
      <title>Convertible to csv format options</title>
      <link>http://blog.rubygreenblue.com/blog/article/convertible_to_csv_format_options</link>
      <description>&lt;p&gt;The latest version of &lt;a href="http://rubygreenblue.com/project/convertible_to_csv"&gt;convertible to csv&lt;/a&gt; can be told how to format particular fields when it returns data for the &lt;code&gt;to_csv&lt;/code&gt; method. The default behaviour is to use the &lt;code&gt;to_s&lt;/code&gt; method for each field. But sometimes you might want to display the data a little differently.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;:format_options&lt;/code&gt; to specify a format method to be called when outputting a field. This is useful, for example, if you have a &lt;code&gt;Time&lt;/code&gt; field and you want to format it differently to how &lt;code&gt;Time.to_s&lt;/code&gt; displays a time.&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Customer&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
  &lt;span class="ident"&gt;acts_as_convertible_to_csv&lt;/span&gt; &lt;span class="symbol"&gt;:header&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
                             &lt;span class="symbol"&gt;:fields&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;%w(&lt;/span&gt;&lt;span class="string"&gt;id firstname lastname email_address&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt;
                             &lt;span class="symbol"&gt;:format_options&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;&lt;span class="symbol"&gt;:lastname&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:format_lastname&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:firstname&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:format_firstname&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;format_firstname&lt;/span&gt;
    &lt;span class="ident"&gt;firstname&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;upcase&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;format_lastname&lt;/span&gt;
    &lt;span class="ident"&gt;lastname&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;reverse&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;As &lt;code&gt;Customer.find(:all).to_csv&lt;/code&gt; is invoked, each time the fields "lastname" and "firstname" are output, instead of calling &lt;code&gt;to_s&lt;/code&gt; on the fields, calls are made to the  &lt;code&gt;format_firstname&lt;/code&gt; and &lt;code&gt;format_lastname&lt;/code&gt; methods respectively and your csv output will contain upcased firstname and reversed lastname.&lt;/p&gt;</description>
      <pubDate>Sat Sep 16 00:43:50 +1000 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/convertible_to_csv_format_options</guid>
      <author>keith</author>
    </item>
    <item>
      <title>Markdown on Rails</title>
      <link>http://blog.rubygreenblue.com/blog/article/markdown_on_rails</link>
      <description>&lt;p&gt;I have renamed the Markdown Template Handler project to &lt;a href="http://rubygreenblue.com/project/markdown_on_rails"&gt;Markdown on Rails&lt;/a&gt;. "Markdown Template Handler" was kinda dull and "Markdown on Rails" has a much better ring to it.&lt;/p&gt;

&lt;p&gt;If you install the new renamed version you will need to change your &lt;code&gt;config/environemt.rb&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;from this&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;markdown_template&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="constant"&gt;ActionView&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;register_template_handler&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;md&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;MarkdownTemplate&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="constant"&gt;ActionView&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;register_template_handler&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;MarkdownTemplate&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="constant"&gt;MarkdownTemplate&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;map_headings_down_by&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;markdown_on_rails&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="constant"&gt;ActionView&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;register_template_handler&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;md&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;MarkdownOnRails&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="constant"&gt;ActionView&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;register_template_handler&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;MarkdownOnRails&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="constant"&gt;MarkdownOnRails&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;map_headings_down_by&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;simple as that.&lt;/p&gt;</description>
      <pubDate>Fri Sep 15 00:26:49 +1000 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/markdown_on_rails</guid>
      <author>keith</author>
    </item>
    <item>
      <title>Convertible to Csv</title>
      <link>http://blog.rubygreenblue.com/blog/article/convertible_to_csv_project_page</link>
      <description>&lt;p&gt;Convertible to csv now has a &lt;a href="http://rubygreenblue.com/project/convertible_to_csv"&gt;project page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've also added some unit tests.&lt;/p&gt;

&lt;p&gt;Convertible to csv allows you to specify that an ActiveRecord model should respond to a &lt;code&gt;to_csv&lt;/code&gt; message. You can also specify if a header row of field names should be used and which fields (and their order) should be used in the csv output.&lt;/p&gt;</description>
      <pubDate>Thu Sep 14 00:37:52 +1000 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/convertible_to_csv_project_page</guid>
      <author>keith</author>
    </item>
    <item>
      <title>Markdown template handler for rails</title>
      <link>http://blog.rubygreenblue.com/blog/article/markdown_template_handler_for_rails</link>
      <description>&lt;p&gt;Writing is all about content. Style and presentation is a separate concern. When I am writing, be it for the web or some documentation or whatever, I like to write pure text. Style and presentation comes later.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; allows me to do that very effectively. I get to concentrate purely on the content of what I am writing and the semantics of the content (this is a heading, this is a list, this should be emphasised...) &lt;/p&gt;

&lt;p&gt;For me, this desire to write plain text extends to writing content for web sites. Of course, html has it place but if I am writing a content page for a client's web site, I would much rather just write the content and not have the html markup of that content get in my way.&lt;/p&gt;

&lt;p&gt;I solved this by writing a rails markdown template handler so I could write web site content in my rails apps in markdown. &lt;/p&gt;

&lt;p&gt;These two images show a rails view (this site's about page) as html and markdown. In the markdown version, the content is free of the clutter of html tags.&lt;/p&gt;

&lt;p&gt;&lt;a href="/blog/images/sample_view_html.jpg"&gt;&lt;img src="/blog/images/.sample_view_html_thumb.jpg" border="0"/&gt;&lt;/a&gt; &lt;a href="/blog/images/sample_view_markdown.jpg"&gt;&lt;img src="/blog/images/.sample_view_markdown_thumb.jpg" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code is released under the MIT licence and can be found at the &lt;code&gt;markdown_template_handler&lt;/code&gt; &lt;a href="http://rubygreenblue.com/project/markdown_on_rails"&gt;project home&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun Sep 03 00:40:00 +1000 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/markdown_template_handler_for_rails</guid>
      <author>keith</author>
    </item>
    <item>
      <title>&lt;code&gt;acts_as_convertible_to_csv&lt;/code&gt;</title>
      <link>http://blog.rubygreenblue.com/blog/article/convert_model_data_to_csv</link>
      <description>&lt;p&gt;&lt;em&gt;update: convertible to csv now has a &lt;a href="http://rubygreenblue.com/project/convertible_to_csv"&gt;project page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A little ruby magic in the form of meta-programming allows you to define your models as being able to output data in csv format. The definition is a DSL style &lt;code&gt;acts_as_convertible_to_csv&lt;/code&gt; with &lt;code&gt;:header&lt;/code&gt; and &lt;code&gt;:fields&lt;/code&gt; as valid specifications.&lt;/p&gt;

&lt;p&gt;Here's how you would use it.&lt;/p&gt;

&lt;p&gt;In your model declaration:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Customer&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
  &lt;span class="ident"&gt;acts_as_convertible_to_csv&lt;/span&gt; &lt;span class="symbol"&gt;:header&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
                             &lt;span class="symbol"&gt;:fields&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;%w(&lt;/span&gt;&lt;span class="string"&gt;id firstname lastname email_address&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;The first row will contain fields names if you specify &lt;code&gt;:header =&amp;gt; true&lt;/code&gt;. You can specify which fields and the order in which they appear by using &lt;code&gt;:fields&lt;/code&gt;. If you omit &lt;code&gt;:fields&lt;/code&gt;, the field list will default to those returned by the &lt;code&gt;human_readable&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Getting the csv data from a collection of records:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="constant"&gt;Customer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_csv&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;You can pass a block:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="constant"&gt;Customer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_csv&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;line&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="comment"&gt;# write the line to a file or something&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;You can also convert individual records to csv:&lt;/p&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="constant"&gt;Customer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:first&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_csv&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;

&lt;h2&gt;The code&lt;/h2&gt;

&lt;span class="ruby_source"&gt; &lt;pre&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ActiveRecord::Base&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.acts_as_convertible_to_csv&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="attribute"&gt;@@use_header_fields&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;

    &lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;param&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;param&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;is_a?&lt;/span&gt; &lt;span class="constant"&gt;Hash&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;param&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt; &lt;span class="symbol"&gt;:header&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;param&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:header&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
          &lt;span class="attribute"&gt;@@use_header_fields&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;param&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt; &lt;span class="symbol"&gt;:fields&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;param&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:fields&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;param&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:fields&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;is_a?&lt;/span&gt; &lt;span class="constant"&gt;Array&lt;/span&gt;
          &lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="constant"&gt;CEEND&lt;/span&gt;&lt;span class="string"&gt;
            def self.csv_header
              %w(&lt;span class="expr"&gt;#{param[:fields].join(' ')}&lt;/span&gt;)
            end
&lt;/span&gt;&lt;span class="constant"&gt;          CEEND&lt;/span&gt;
        &lt;span class="keyword"&gt;else&lt;/span&gt;
          &lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="constant"&gt;CEEND&lt;/span&gt;&lt;span class="string"&gt;
            def self.csv_header
              field_names = Array.new
              self.content_columns.each do |column|
                field_names &amp;lt;&amp;lt; column.name
              end
              field_names
            end
&lt;/span&gt;&lt;span class="constant"&gt;          CEEND&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="constant"&gt;CEEND&lt;/span&gt;&lt;span class="string"&gt;
      def self.use_header_fields
        @@use_header_fields
      end

      def to_csv
        line = &amp;quot;&amp;quot;
        self.class.csv_header.each do |field_name|
          line = line + &amp;quot;,&amp;quot; + self.send(field_name).to_s
        end
        # remove first ', '
        line.gsub! /^,/, ''
      end
&lt;/span&gt;&lt;span class="constant"&gt;    CEEND&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="comment"&gt;# Allow a collection class to repond to to_csv&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Array&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;to_csv&lt;/span&gt;&lt;span class="punct"&gt;(&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;data&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Array&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
    &lt;span class="comment"&gt;# check to see if the objects in the array are capable of to_csv    &lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;method_defined?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:to_csv&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;use_header_fields&lt;/span&gt;
        &lt;span class="ident"&gt;data&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;csv_header&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;,&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
        &lt;span class="keyword"&gt;yield&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;csv_header&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;,&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;block_given?&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;object&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="ident"&gt;data&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;object&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_csv&lt;/span&gt;
        &lt;span class="keyword"&gt;yield&lt;/span&gt; &lt;span class="ident"&gt;object&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_csv&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;block_given?&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;data&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/span&gt;</description>
      <pubDate>Mon Jul 17 02:52:13 +1000 2006</pubDate>
      <guid>http://blog.rubygreenblue.com/blog/article/convert_model_data_to_csv</guid>
      <author>keith</author>
    </item>
  </channel>
</rss>
