環境
Macbook Pro
Rails 5.2.2
Ruby 2.6.3
問題
以下の関連付けが行われているときに大量の factory を作成する方法を研究しました。
user > customers > products の2段の関連付けが行われているとします。
has_many :customers
belongs_to :user
has_many :products
belongs_to :customer
解決方法
色々試行錯誤して、半日かかってしまいました...
私の解法はこちらです。
ユーザーの作成方法
まずは簡単に2人のユーザーを作ります。
FactoryBot.define do
%w(user1 user2 user3).each do |user|
factory user.to_sym, class: User do
email {"#{user}@example.com"}
password {'password'}
end
end
require 'rails_helper'
describe "User" do
let!(:user1) { create :user1 }
let!(:user2) { create :user2 }
it 'user check' do
p user1
p user2
end
end
カスタマーの作成方法
次に、
user1 に関連づけられた customer1_1, customer1_2
user2 に関連づけられた customer2_1
を作成します。
FactoryBot.define do
%w(customer1_1 customer1_2 customer2_1).each do |custmer|
factory customer.to_sym, class: Customer do
name { customer }
end
end
rspec でカスタマーを作成するときに、オプション「user: user1」で関連づけることがポイントです。これをしないと、エラーになります。
describe "Customer" do
let!(:user1) { create :user1 }
let!(:user2) { create :user2 }
let!(:customer1_1) { create(:customer1_1, user: user1) } # user1 と関連付ける
let!(:customer1_2) { create(:customer1_2, user: user1) } # user1 と関連付ける
let!(:customer2_1) { create(:customer2_1, user: user2) } # user2 と関連付ける
it 'customer check' do
p user1
p user2
p customer1_1
p customer1_2
p customer2_1
end
end
プロダクトの作成方法
最後に、
customer1_1 に関連づけられた product1_1_1, product1_1_2
customer1_2 に関連づけられた product1_2_1
を作成します。
FactoryBot.define do
%w(product1_1_1 product1_1_2 product1_1_3 product1_2_1).each do |product|
factory product.to_sym, class: Product do
name { product }
end
end
end
先ほどと同じようにプロダクトを作成するときに、オプション「customer: customer1_1」で関連づけることがポイントです。仕組みがわかると簡単。これで大量のデータが作成できますね。
require 'rails_helper'
describe "Product" do
let!(:user1) { create :user1 }
let!(:customer1_1) { create(:customer1_1, user: user1) } # user1 と関連付ける
let!(:customer1_2) { create(:customer1_2, user: user1) } # user1 と関連付ける
let!(:product1_1_1) { create(:product1_1_1, customer: customer1_1) } # customer1_1 と関連付ける
let!(:product1_1_2) { create(:product1_1_2, customer: customer1_1) } # customer1_1 と関連付ける
let!(:product1_2_1) { create(:product1_2_1, customer: customer1_2) } # customer1_2 と関連付ける
it 'product check' do
p user1
p customer1_1
p customer1_2
p product1_1_1
p product1_1_2
p product1_2_1
end
end
もし間違っているところがあれば教えてください。よろしくお願いいたします。
参考
ありがとうございます。参考にさせていただきました。
[Rspec] 関連で「バリデーションに失敗しました」が発生するとき
追記
もうお済みと思いますが、以下の設定をしていないとエラーになりますので追記します。
config.include FactoryBot::Syntax::Methods