FactoryGirl Inheritance attribute already defined
Asked Answered
Q

1

8

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
Quinnquinol answered 3/2, 2014 at 18:18 Comment(0)
S
11

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.

Skimpy answered 3/2, 2014 at 18:27 Comment(1)
Cool! You nailed it, right on the head. Thanks Joe. (I'll accept it in 1:30 mins, haha)Quinnquinol

© 2022 - 2024 — McMap. All rights reserved.