to_csv update (nearing Round #2) 04 Jan 2007
Round #2 of the to_csv functionality is nearing completion. The updates so far are:

  • supports associations via the :include option on a per model object basis
  • supports custom headers through the model class

It will work on an ActiveRecord model object itself or an array of ActiveRecord model objects that are returned from any “find” method call.

Basic :include option

The :include option will bring in an association that is created with belongs_to or has_many declarations.

Here is a basic example for a belongs_to association to be included in the CSV results with default options:

csv = People.find( :all ).to_csv( :include=> \[ :address \] )

If you haven’t been following to_csv functionality prior to this posting the to_csv method does support toggling on/off of the CSV headers:

  • :headers=>true
  • :headers=>false

Updated :headers Option

To detour from the :include options for a moment, the :headers option has been updated to accept:

  • an array of column names as Symbols or Strings
  • a Hash of column name to header name mappings as Symbols or Strings

Here are a few examples of the new headers option in use:

# using symbols
csv = People.find( :all ).to_csv( :headers => [ :first\_name, :last\_name ]  }

# using strings
csv = People.find( :all ).to_csv( :headers => [ 'first\_name', 'last\_name' ]  }

# using a Hash to supply custom headers
csv = People.find( :all ).to_csv( :headers => { :first\_name=>'FirstName', :last_name=>'LastName' }

Since Arrays are ordered the CSV columns will be in the order of the Array. Since Hashes aren’t ordered the order of the columns will be done alphabetically based on the field name.

Intermediate Usage Of :include

The :include option can take:

  • an Array of Strings or Symbols denoting the name of the association
  • a Hash of Hashes mapping the association name to an options Hash

The options Hash is what you’re already passing into the to_csv method. If you use the Hash form of :include you get the ability to embed different options per each association included.

Here are some more intermediate examples:

people = People.find( :all )

# Using a Hash to specify the column you want from the Address relationship
people.to_csv( :include=>{ :address=>{ :only=>[ :street, :city, :state, :zip ] } } )

# Using a top level options to include only certain fields from each person and
# then options to include certain fields from each person's address.
people.to_csv( :only=>\[ :first_name, :last_name \],
   :include=>{ :address=>{ :only=>\[ :street, :city, :state, :zip \] } } )

# Modification of the last example to use custom headers
people.to_csv( :headers=>{ :first_name=>"FName", :last_name=>"LName" } ,
   :include=>{ :address=>{ :headers=>{ :city=>"Hometown", :state=>"ST" } } } )

That’s a brief summary for where the state of affairs is at for now. If you want more information please read all of the nice tests by “checking out”:http://rubyforge.org/scm/?group_id=2113 the SVN repository.

There are some other usages that you will be able to do like (see below) but the tests and functionality has not been intentionally implemented although it may/may work off from existing functionality:

  • support multiple :include options for multiple associations
  • embed :include options inside of :include options for chaining associations

One thing I don’t like about all of this so far is all of the curly braces, brackets and potentially parenthesizes. The more :includes you want to have, the more curly braces you’re going to have most likely.

I’m trying to think of a block like declarative syntax to handle this, but I haven’t come up with any worthwhile yet. If you’ve got any ideas I’m all ears.

Upcoming 0.4.0 release

This will be launched in a 0.4.0 release which should be soon. I’ve got to be out of town part of this weekend, and the most of next week so I am going to see if I can crunch it in before the next Monday.


blog comments powered by Disqus