stevengharms.com

Sententiae viri ex temporibus duobus

Rails: Loading Test Data With Fixtures

Rails canonical story is:

  • “Fixtures are used to load sample data before a unit test”.
  • “Migrations are used to build DB tables and alter structure of contents thereof ( e.g., delete the "name” column and split the field on comma and put the resultant entries into the “firstname” column and the “lastname” column )"

But what if you need to bring in some good data – not test data, but data that you want for testing and seeing how things look with a “real” data set? What then smarties?

Here was my situation: I had entered data via the scaffolded interface and the the data included many unicode characters (&258;eae, etc.). I wrote a little JavaScript table specifically to make entering these characters easy from an English keyboard.

I knew that I was going to invariably mess up the data and wanted to have the ability to get this preliminary data set back in ( it’s just safer that way ).

Furthermore the datas contained Unicode and I’ve just not had time to wrap my head around “entering Unicode values via command line into PostGres.

I dumped the data to a YML file with:

[code lang="ruby"]
x=File.open("models.yml")  
x.puts Model.find(:all).to\_yaml  
x.close  
[/code]

Looking at that Yaml data, I have my records.

I put that information into ../test/fixtures/models.yml

This file requires a bit of editing.

You will start with entries that look like:

    - !ruby/object:Model 
      attributes: 
        updated_at: 2008-01-04 19:32:10.874607
        id: "5"
        classification: Fourth
        created_at: 2008-01-04 19:32:10.874607
      attributes_cache: {}

You want to turn this into….

first:
  updated_at: 2008-01-04 19:32:10.874607
  id: "5"
  classification: Fourth

That is, reduce the indents of the “meaty data”, remove the “- !ruby” declaration and then put a numbering tag ( “first” ). This will help you import. You may find it handy to try the following in the console:

[code lang="ruby"]
directory="./test/fixtures"
require 'active_record/fixtures'
Fixtures::create_fixtures( directory, "models")
Conjugation.find(:all)
[/code]

Obviously, good data here is a good sign; errors, a sign of more work.

Then with rake db:load:fixtures I could get my data back in….but I wanted to make this addition hinge on a migration, so that I could move forward and backwards in the migration queue. Thanks to the skateboard book p.273 I found a way.

First I created a migration script/generate migration importBaselineData

Edit the 0xx_import_baseline_data.rb

[code lang="ruby"]
require 'active_record/fixtures'  

class LoadSampleData < ActiveRecord::Migration  
  def self.up  
    directory = File.join(File.dirname(__FILE__), "../../test/fixtures")  
    Fixtures::create_fixtures( directory, "models")  
  end  

  def self.down  
    Model.delete_all  
  end  
end  
[/code]

Thus with a rake db:migrate my migration with data entry gets entered.

Comments