Factory Girl create association with existing object

associations, factory-bot, ruby-on-rails

Solution

You could achieve what you want by both not using a factory for your Gender instances and using callbacks in your Customer factory.

You're not gaining a lot from the Gender factory as it stands (although I appreciate it may be simplified for the purposes of asking this question). You could just as easily do this to get a Gender:

Gender.find_or_create_by_code!('Male')

Then in your Customer factory you can use a before callback to set the Gender:

factory :dumas, :class => Customer do
  first_name 'Mary'
  last_name 'Dumas'
  before_create do |customer|
    customer.gender = Gender.find_or_create_by_code!('Female')
  end
end

The format for using callbacks in factory_girl has recently changed so if you're using 3.3 or later you'll need to do:

before(:create) do |customer|

instead of `before_create`.

If creating a gender is more complex than your example you can still create the genders using a factory but hook them up with your customers using callbacks using `find_by_code!` insteand of `find_or_create_by_code!`.

Problem

I am new to FactoryGirl and I am trying the following simple scenario? ``` factory :female, :class => Gender do code 'Female' end factory :male, :class => Gender do code 'Male' end factory :papas, :class => Customer do first_name 'Jim' last_name 'Papas' association :gender, :factory => :male, :strategy => :build end factory :dumas, :class => Customer do first_name 'Mary' last_name 'Dumas' association :gender, :factory => :female, :strategy => :build end ``` Then in my test: ``` create(:male) create(:female) create(:papas) create(:dumas) ``` Note that Customer class has an assocation `belongs_to` `Gender` class and a validation rule that says that `gender_id` should be present. I also have a validation on `Gender` class for uniqueness on code. On `create(:papas)` statement above, in my test, I get the error that the `Customer` that is going to be created is not valid, because `gender_id` is `nil`. If I remove the `:strategy => :build` on `Customer` `:papas` factory association with gender, then I will get an error, that when trying to create `:papas`, the code for the gender already exists. What do I need to do so my tests create the data as required above? Note that I want to have genders created without customers also, in other tests. Do not tell me to create the customers with factory create commands and let the customers create the genders at the same time. This will not work if I try to create two customers of the same gender too. Also, there has to be a better answer than the one: ``` @male = create(:male) @female = create(:female) create(:papas, :gender => @male) create(:dumas, :gender => @female) ``` (When using fixtures these things were ready out-of-the-box. Shall I return back to fixtures?)

Original source