I made a many-to-many relationship with Rspec and tested it with SystemSpec. Due to the complexity of the original table structure, I had a lot of trouble, so I will summarize the notes below.
The execution completion is as follows.
The table structure looks like this. The main tables are ʻoffices (branch office of a company) and shops (stores that are business destinations), and ʻoffice (branch office) opens ʻevebt, and the stores shopsthat are business destinations there.Join. shops always has some category.
Due to the model method, when I made factory of ʻevents, I neededshops` associated with it. However, due to the structure, if I wrote it like this, an error occurred.
let!(:shop){FactoryBot.create(:shop)}
let!(:event){FactoryBot.create(:event)}
#=>Here, the structure was such that an error would occur if there was no shop associated with the event.
let!(:event_shops){FactoryBot.create(:event_shop, event: event, shop: shop)}
Therefore, I decided to create a factory that can define the related shop at the same time when the factory of ʻevent` is created.
The created Factory is as follows.
spec/factories/events.rb
FactoryBot.define do
  factory :event do
    office_id { nil }
    name { "Test event" }
    
    trait :with_shops do
      after(:create) do |event|
        category = FactoryBot.create(:category, :sequence)
        create_list(:shop, 1, events: [event], category: category)
      end
    end
  end
end
First, create a trait called with_shops in the factory of ʻevent so that you can also create the associated shop when you create ʻevent. Make it possible to create multiple shop factories with create_list (only one because only one is needed here), and [event] so that multiple instances of ʻevent can be entered from ʻevents. It is expressed as and an array.
In addition, I will explain later that category is purposely called using trait.
spec/factories/categories.rb
FactoryBot.define do
  factory :category do
    name { "Medical system" }
    trait :sequence do
      sequence(:id, 100)
      name { "Clothing system" }
    end
  end
end
spec/system/events_spec.rb
let!(:event) { FactoryBot.create(:event, :with_shops, office: office, shops: [shop]) }
#You can't apply category to shop from here
Next, in the factory of category, ʻeventis generated multiple times in the view. Therefore, thecateogory of the shop generated at the same time must be set to a different ʻid (FK) each time, or an FK duplicate error will occur.
Also, when trying to apply category from system spec to shops of ʻevent, when trying to create a factory for shopinspec / factories / events.rb`," The foreign key does not exist "and I got an error.
Therefore, using sequence, I tried to create different categories of ʻid` (FK) one by one.
It took a long time to resolve, but I'm glad I managed to resolve it! This time, the structure of the DB was complicated, so I had to write such a complicated Spec, but In the future, I would like to solidify the DB design so that simpler tests can be done. .. .. ..
▼ Articles that I especially referred to -Set up "many-to-many" and "multiple one-to-many" associations in Factory Girl -Use Factorybot traits to prepare data with complex associations with double has_many -FactoryBot (formerly FactoryGirl) sequence and .next
Recommended Posts