Jake
Jake

Reputation: 1370

Associations with FactoryBot in Rails: Validation Failed

I have the following in my locations factory:

FactoryBot.define do
  factory :location do
   name 'MyString'
   hours_operation 'MyString'
   abbreviation 'MyString'
   address_1 'MyString'
   address_2 'MyString'
   city 'MyString'
   state 'MyString'
   postal_code 1
   phone 'MyString'
   fax 'MyString'
   association :region
 end
end

I have the following in my regions factory:

FactoryBot.define do
  factory :region do
    name 'MyString'
   end
 end

Region has_many locations and Locations belongs_to region.

However in my testing I keep getting Validation failed: Region must exist.

I have tried the following:

after(:create) do |location, _evaluator|
 create_list(:region, evaluator.region, location: location)
end

association :region, factory: region

before(:create) do |region|
  region.location << FactoryBot.build(:location, region: region)
end

I've also tried in regions factory:

factory :region_with_location do
  after(:create) do |region|
   create(:location, region: region)
   end
end

In locations factory:

association :region, factory: :region_with_location

In each case I still keep getting: Validation failed: Region must exist.

Upvotes: 5

Views: 9786

Answers (1)

user5482251
user5482251

Reputation:

Because Location belongs_to Region, an instance of Region must be created in the test database before building and saving a Location. This is why your code doesn't work here, as @Niklas says:

after(:create) do |location, _evaluator|
 create_list(:region, evaluator.region, location: location)
end

What you could do is the reverse: Build a list of locations via association after a region is created.

FactoryGirl.define do
  factory :region do
    name 'MyString'

  factory :region_with_locations do
    transient do
      locations_count 5
    end

    after(:create) do |region, evaluator|
      create_list(:location, evaluator.locations_count, region: region)
    end
  end
end

You can also look into using a before(:create) callback to create a region before assigning it to a location.

Upvotes: 1

Related Questions