The State of Vue.js Report 2025 is now available! Case studies, key trends and community insights.
Table of Contents
Recently, we were looking at how to set up a many-to-many relationship with FactoryBot. Unfortunately, Google wasn’t all that helpful in solving this problem, so we had to figure out this issue on our own. We found that the only possible solution is to use the after_create
callback as the example below shows:
FactoryGirl.define do
factory :book do
sequence(:title) { |n| "Book #{n}" }
end
factory :user do
sequence(:email) { |n| "user#{n}@example.org" }
end
factory :user_with_book, parent: :user do
after_create do |user|
user.books << FactoryGirl.create(:book)
end
end
end
This solution wasn't enough for us though, because we also needed to share a book between two users. Our first attempt to set up this connection had to be done manually like this:
let(:book) { FactoryGirl.create(title: "The Winds of Winter") }
let(:jon) { FactoryGirl.create(:user) }
let(:arya) { FactoryGirl.create(:user) }
before do
jon.books << book
arya.books << book
end
After digging a bit deeper though, we discovered that to DRY this we can actually use the after_create
callback too. Just use the lesser known ignore
and evaluator
pair like this:
FactoryGirl.define do
factory :book do
sequence(:title) { |n| "Book #{n}" }
end
factory :user do
sequence(:email) { |n| "user#{n}@example.org" }
end
factory :user_with_book, parent: :user do
ignore do
book { FactoryGirl.create(:book) }
end
after_create do |user, evaluator|
user.books << evaluator.book
end
end
end
Finally in specs
we can easily set up users with the same book like this:
let(:book) { FactoryGirl.create(title: "The Winds of Winter") }
let(:jon) { FactoryGirl.create(:user_with_book, book: book) }
let(:arya) { FactoryGirl.create(:user_with_book, book: book) }
Now we have much cleaner code!
Confidently build your next app
Our devs are so communicative and diligent you’ll feel they are your in-house team. Work with experts who will push hard to understand your business and meet certain deadlines.