Topic: Factory Girl: overriding a foreign key / association

If I have a factory that assembles the associations of a record, I can't figure out how to call the factory to override the foreign key - it gets set to the association from the factory file no matter what I pass to Factory.create().   I want to do this so I can spec out the behavior of the record validations when the foreign key is nil, or when it points to a non-existent record.

Suppose I have these two classes and their factories:

class Degree < ActiveRecord::Base
  belongs_to :institution, :foreign_key => "institution_code"
  # ... other associations ...

   def validate                                                
    if institution_code.nil? or institution.nil?
      errors.add(:institution_code, "Must be a valid institution")
    end
  end      
end

class Institution < ActiveRecord::Base
end

Factory.define :degree do |d|
  d.association :institution, :factory =>:institution
  # other attributes and associations here
end

Factory.define :institution do |i|
  i.institution_code "00001"
  i.name "International Institute of Rails"
end

The problem with this approach is that even if I call:

Factory(:degree, :institution_code => nil)   or
Factory(:degree, :institution_code => '00002')

I get back a Degree object that has institution_code set to "00001".   

I could of course create a specifically defined :degree factory that didn't set up associations, so I could just set the foreign keys as attributes.  But I actually have 5 associations to test, and each needs to fail if it's set to nil or to point to a non-existent record.  So that would mean for each nil association I wanted to test, I'd have to manually set the other 4 to valid values; that gets tedious in a hurry and defeats the purpose of using factories.

Thoughtbot docs don't explain how to do this, and Google has been unhelpful on this issue.  Any advice appreciated, thanks.

Last edited by IdahoEv (2009-09-23 22:55:42)

Re: Factory Girl: overriding a foreign key / association

In fact I am also interested in this issue.
Any thoughts if this is possible at all?

Re: Factory Girl: overriding a foreign key / association

I was unable to get it to work the way I wanted (just overriding the foreign key with a non-valid value) -- this seems to be an unavoidable deficiency of Factory Girl.   

But I could get it to work, sort of, by creating an invalid and unsaved associated record, like this:

Factory(:degree, :institution => Factory.build(:institution, :code => nil))
Factory(:degree, :institution => Factory.build(:institution, :code => '00002'))

This wasn't testing exactly the same thing, but it did exercise my validations nonetheless.

Aside from that, I can see a couple other approaches:
  1) Use fixtures.  (I know, the horror - but I actually think fixtures are still better than factories for some things)

  2) Use a factory, but 'manually' edit the created object afterward:

  
   foo_degree = Factory(:degree)
   foo_degree.institution=nil
   foo_degree.save

   or

   foo_degree = Factory(:degree)
   foo_degree.institution_code = '00002'
   foo_degree.save

Re: Factory Girl: overriding a foreign key / association

Thanks for taking time to post back!
This info helps me a lot.

Re: Factory Girl: overriding a foreign key / association

I believe that you must override the association, not the foreign key.  In the first example above the appropriate code would be

foo = Factory(:degree, :institution => Institution.first)

or something similar.

Last edited by jackrg (2011-11-05 18:17:27)