Reputation: 79
Hi there, I have the following 3 models:
Location < ApplicationRecord
StagingLocation < Location
Package < ApplicationRecord belongs_to :location
I can set-up associations to create a valid Package factory by simply calling the factory of the StagingLocation instead of the Location. As per the following code:
package_spec.rb:
describe "package validation" do
let(:package_location) { create(:staging_location) }
it "has a valid factory" do
expect( create(:package, location: package_location) ).to be_valid
end
However, this will not pass FactoryBot.lint
1. lint throws an error on the creation of a Location
FactoryBot.define do
factory :location do
type { "StagingLocation" }
name { "Location" + Faker::GreekPhilosophers.unique.name }
end
end
throws this error
The single-table inheritance mechanism failed to locate the subclass: '0'. This error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this column if you didn't intend it to be used for storing the inheritance class or overwrite Location.inheritance_column to use another column for that information. (ActiveRecord::SubclassNotFound)
2. Calling the staging_location factory fails with a
NoMethodError
because Package is looking for a location
FactoryBot.define do
factory :package do
staging_location
name { "TEST-" + rand(99).to_s }
end
end
I see three possible ways to get around this but can't seem to find FactoryBot syntax to accomplish them:
a) Create a Location factory
b) Create a StagingLocation factory that returns a Location class using the base_class method or similar
c) Tell the Package factory to accept the staging_location as a location factory
d)Ignore the error since at the end of the day, my factories are being created as expected.
Any suggestions?
Upvotes: 0
Views: 706
Reputation: 79
As per this issue on the FactoryBot github page,
STI can be defined by declaring the child factory within the parent factory and declaring the STI class.
In my case this worked out as follows:
FactoryBot.define do
factory :location, class: "StagingLocation" do
name { "Staging " + rand(99).to_s }
end
end
FactoryBot.define do
factory :package do
name { "Package " + rand(99).to_s }
location { create(:staging_location, location: location) }
end
end
Upvotes: 0