2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[RSpec] FactoryBot で関連づけられた 大量の factory を作成する

Last updated at Posted at 2019-09-07

環境

Macbook Pro
Rails 5.2.2
Ruby 2.6.3

問題

以下の関連付けが行われているときに大量の factory を作成する方法を研究しました。
user > customers > products の2段の関連付けが行われているとします。

app/models/user.rb
has_many :customers
app/models/customer.rb
belongs_to :user
has_many :products
app/models/product.rb
belongs_to :customer

解決方法

色々試行錯誤して、半日かかってしまいました...
私の解法はこちらです。

ユーザーの作成方法

まずは簡単に2人のユーザーを作ります。

spec/factories/user.rb
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
spec/models/user_spec.rb
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
を作成します。

spec/factories/customer.rb
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」で関連づけることがポイントです。これをしないと、エラーになります。

spec/models/customer_spec.rb
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
を作成します。

spec/factories/product.rb
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」で関連づけることがポイントです。仕組みがわかると簡単。これで大量のデータが作成できますね。

spec/models/product_spec.rb
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] 関連で「バリデーションに失敗しました」が発生するとき

追記

もうお済みと思いますが、以下の設定をしていないとエラーになりますので追記します。

spec/rails_heler.rb
  config.include FactoryBot::Syntax::Methods
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?