Advanced YAML Fixtures Gotchas
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
-
I think that Fixtures.identify will do what you want – given a label, it returns the ID used.
-
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.
-
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: endSo it should work pretty much anywhere, and any fixture with the same label will have the same ID.
