views:

892

answers:

2

Can anyone suggest a better way to make a factory use a pre-built model instance for its association? For example, so that it would be possible below to define a child of the Message factory so that a call to Factory(:my_message) could substitute for Factory(:message,:sender=>@me) ?

Sometimes the setup hash is more involved than in this contrived example, or is just repeated in so many tests that it would seem better to push it down into the factory.

One alternative I can think of is to define a test helper method such as create_message_owned_by(@me), but I'm hoping there's a way within factory_girl itself.

factory_girl factories:

Factory.define :sender do |s|
  sender.name "Dummy name"
end

Factory.define :message do |msg|
  msg.text "Dummy text"
  msg.association :sender
end

Factory.define :my_message, :parent=>:message do |msg|
  msg.text "Dummy text"
  ### ? what goes here for msg.association :sender ? ###
end

MessagesControllerTest excerpt (using shoulda):

context "on GET /messages" do
  setup do
    @me = Factory(:sender)
    @my_message = Factory(:message,:sender=>@me)
    @somebody_elses_message = Factory(:message)
    sign_in_as(@me)
    get :index
  end
  should "only assign my messages" do
    assert_contains(assigns(:messages), @my_message)
    assert_does_not_contain(assigns(:messages), @somebody_elses_message)
  end
end
+1  A: 

I don't know if this is what you're looking for, but if you first create message you can fetch the sender through that and assign it to @me.

@my_message = Factory(:message)
@me = @my_message.sender

Does that help at all?

ryanb
Ryan McCuaig
The question is, what makes the current user different from any other user? Is it just the fact that it is assigned to the @me variable? That is outside the scope of a factory and would introduce an unclear dependency.
ryanb
You're right. On reflection, hard-coding @me (or similar) into the factory is dumb. The factory needs to take a parameter, which it of course does very generally as the trailing hash in the form of `Factory(:message,:sender=>@me)`.This would seem to bring it back to abstracting out a helper like `create_message_owned_by(@me)` to wrap specific repetitive association setups.
Ryan McCuaig
A: 

Ignoring for a minute the problem of creating an unclear dependency, the example above could be handled with the new callbacks in FactoryGirl 1.2.3. There are now after_build and after_create callbacks, so that you can perform operations on created objects after they already exist in the database (and have an id to grab on to, etc).

See also this question and this thread from the factory_girl mailing list.

Ryan McCuaig