Advanced YAML Fixtures Gotchas

written by jared on December 11th, 2007 @ 02:55 PM

I was very excited to use the new Advanced YAML Fixtures introduced in Rails 2.0, so I set about updating my code in an Edge Rails application I've been working on for the past year or so. There are a few caveats in using the new fixture styles, though.

The Fixtures are introspective, so if you've overridden the default name of an association in your model, you'll need to use that new name in your fixture. With the following code,

class Worker < ActiveRecord::Base
  belongs_to :status, :class_name => 'WorkerStatus', :foreign_key => 'worker_status_id'
  ...
end

The key for worker_status: should actually just be status: in the workers.yml fixture file.

The larger problem I encountered was in using a mix of IDs and fixture record names. I use a testing framework, TestRig, which was written by Mike Clark and Dave Thomas for the Pragmatic Studio. The TestRig framework takes in ID parameters of fixtures in the database, and loads them accordingly. This falls apart with the new status: full_time style of declaring relationships in fixtures, because the former relies on a 'known' ID, and the new style generates a fairly random ID instead. This leads to a bunch of broken relationships throughout the test suite.

According to the API documentation, the generated ID is constant, so I could discover that ID and use it in the TestRig calls which require an integer key, but then I've essentially lost all benefit of using the Advanced YAML Fixtures, and added some crazy complexity to my tests as well.

Comments

  • Matt on 11 Dec 17:15

    I think that Fixtures.identify will do what you want – given a label, it returns the ID used.

  • Jared on 11 Dec 17:31

    I think part of the issue with using TestRig is the macro-style class methods for defining valid attributes; I can’t seem to use something simple like :user_id => users(:jared).id (such code gives a Top Level Constant error).

    I guess I have two questions for Fixtures.identify that I’ll need to research: How does it handle label collisions (if I have a worker whose label is joe as well as a user whose label is joe), and if it will perform the identification when called as part of a class method in a Unit or Functional test.

  • Matt on 11 Dec 19:25

    A quick glance at the source should answer your questions:

    
         # File vendor/rails/activerecord/lib/active_record/fixtures.rb, line 531
    531:   def self.identify(label)
    532:     label.to_s.hash.abs
    533:   end
    

    So it should work pretty much anywhere, and any fixture with the same label will have the same ID.