factory_girl and a tree of related objects
My fixture replacement of choice is factory_girl. In general, it’s been very good. But, as with any tool, there are edge cases that just don’t work as well. This is a common use case for me. It seems common enough that there should be a good solution for it, but I haven’t googled it up yet.
The problem
The pattern is that I have a root model, with a couple of collections living inside it.
One of the collections is made of objects that are just nested…
… and the other is associated with both.
(An obvious solution to this problem is to drop the
belongs_to :site
from Post, but that’s not always
desirable. Sometimes it just doesn’t work, if Post and
Member had a habtm association, and neither depended on
the other’s existence.)
The straightforward factories for the models above is this:
The problem I run into is this: If I do Factory(:post)
, then
the post[id:1] has an author[id:1] linked to site[id:1]. But
post[id:1] is linked to site[id:2]!
Solution: Use an after_build callback
The best solution I’ve come up with is to define these associations
that depend on each other in an after_build
block. The simple way
to do it is just to try to hook up common associations.
Solution improved: after_build and a test-global context.
Another method that I like is to create a context class. Because most of my tests deal with data that is well-formed (e.g. it is unexpected that the application would contain a post that links to a member from a different site), the context class can store a global-to-test site instance.
This works pretty well for me, but it seems like there should be a better way.
I think what I want is the concept of a fixed Site
instance for the duration
of a given test, so, a replacement for the TestContext.
The exact code in this article has not been tried, so it probably doesn’t run. Hopefully the intent is clear enough.