Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FactoryGirl Inheritance attribute already defined

Alright guys. How does this even make sense? The two nested factories (which is considered an inheritance by FactoryGirl) should not conflict with each other. What the heck is going on? Either it's not inheritance or it is. I don't know why they'd call it inheritance if it weren't. Am I just doing something wrong? (Notice f.account_type)

Take a look at the factory definition below.

factory :partner do |f|
  f.company_name { Faker::Company.name }
  f.username { Faker::Internet.user_name }
  f.password { Faker::Internet.password }
  f.password_confirmation { password }
  f.pid { Faker::Lorem.word }

  f.association :primary_contact

  # Inherited
  factory :business_partner do
    f.account_type "business"
    f.tax_id { Faker::Company.duns_number }
  end

  # Inherited
  factory :personal_partner do
    f.account_type "personal"
    f.ssn { Faker::Company.duns_number }
  end

end

When I run my tests, I get this error.

Failure/Error: partner = FactoryGirl.create(:business_partner)
  FactoryGirl::AttributeDefinitionError:
    Attribute already defined: account_type

And just for completeness, my spec.

# spec/models/partner.rb
require 'spec_helper'
require 'pp'

describe Partner do

  it "has a valid factory" do
    partner = FactoryGirl.create(:business_partner)
    partner.should be_valid
    puts partner
  end

  it "is invalid without a firstname" do
#    FactoryGirl.build(:partner_contact, first_name: nil).should_not be_valid
  end

  it "is invalid without a lastname" do
#    FactoryGirl.build(:partner_contact, last_name: nil).should_not be_valid
  end

  it "is invalid without an email address" do
#    FactoryGirl.build(:partner_contact, email: nil).should_not be_valid
  end

  #it "returns a contact's fullname as a string"

end
like image 260
Volte Avatar asked Feb 03 '14 18:02

Volte


1 Answers

Within the business_partner and personal_partner factory definitions, you're referring to f, which is the definition for the partner factory. This means that, even though the account_type definitions occur within the child factories, both are being defined on the parent factory.

The easiest way to fix this in newer versions of FactoryGirl is to remove the block parameter altogether.

factory :partner do
  company_name { Faker::Company.name }
  username { Faker::Internet.user_name }
  password { Faker::Internet.password }
  password_confirmation { password }
  pid { Faker::Lorem.word }

  association :primary_contact

  # Inherited
  factory :business_partner do
    account_type "business"
    tax_id { Faker::Company.duns_number }
  end

  # Inherited
  factory :personal_partner do
    account_type "personal"
    ssn { Faker::Company.duns_number }
  end
end

If you like the block parameters, just make sure to accept a parameter to each factory definition and use a different variable name.

like image 83
Joe Ferris Avatar answered Nov 13 '22 04:11

Joe Ferris