Memos on “Advanced YAML Fixtures” of RoR

YAML Fixtures in Rails 2.0 have some pretty cool features. One of them is “auto generated primary IDs”, and another cooler one is “Label references for associations (belongs_to, has_one, has_many)”. You can find explanations and examples of them in the link above. But there is a pitfall to notice: the second feature actually depends on the first one. In other words, “Label references for associations” may not work if you’re not applying auto generated IDs in your fixture.

The method behind the scene of auto generated IDs feature is Fixture#identify, which is simply a hash process on the label of the fixture row. When the fixture loader handles the label references, it will call the Fixture#identify method directly to get the ID of associated models. So here is a typical failure case.

### in pirates.yml
reginald:
   id: 1
   name: Reginald the Pirate
   monkey: george
### in monkeys.yml
george:
   name: George the Monkey
   pirate: reginald # the fixture loader will use the result of Fixture.identify('reginald') here! not "1".

Using hashed label as auto generated ID is a pretty smart idea. It avoids the troubles to find fixture references between each other and the pain of detecting fixture reference loop. There is a plugin named “Fixture Reference” which actually solves the problem in this tedious way. But I prefer the Rails 2.0 way because it looks more elegant and smarter.

However, sometimes we still need to include primary IDs in the fixtures, for some constants like country/state/city/timezone. Sometimes it’s easier to export them from the database as CSV, since fixture loader can handle CSV files. In this case, refer them in other fixtures by ID, not by label. Or to be safer, don’t give these fixtures label at all.

So the best practice and maybe the “correct” way to use Rails 2.0 fixture is : Specify either ID or label , don’t mix them in a single fixture file.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.