FactoryBotで中間テーブルのテストデータを用意する方法
FactoryBotでテストデータの中間テーブルを用意する方法がわからず、少し詰まったのでメモ。
想定
想定としてUserモデルとGroupモデルが存在し、n対nの関係であるとする。 中間テーブルのモデル名はGroup_userとする。
app/models/user.rb class User < ApplicationRecord has_many :group_users, dependent: :destroy has_many :groups, through: :group_users end app/models/group.rb class Group < ApplicationRecord has_many :group_users, dependent: :destroy has_many :users, through: :group_users end app/models/group_user.rb class GroupUser < ApplicationRecord belongs_to :group belongs_to :user end
FactoryBotの記述方法
レコードの関連付けを行う場合は色々な書き方があるが、ここではその一例を紹介する。 基本的には関連付けはtraitとcallbackを用いて記述する。
spec/factories/user.rb FactoryBot.define do factory :user do sequence(:name) { |n| "test_user#{n}" } sequence(:email) { |n| "test_email#{n}@example.com" } sequence(:password) { "password" } trait :user_with_groups do after(:build) do |user| # after(:build)とした場合、createの場合もcallbackが走る user.groups << build(:group) end end end end spec/factories/group.rb FactoryBot.define do factory :group do equence(:name) { |n| "test_user#{n}" } end end
上記の書き方をしておくと、userデータを作成後、traitでuserに紐づくgroupの作成をするかしないかを切り替える事が出来る。
# Userに紐づくGroupを作成する場合 user = create(:user, :user_with_groups) # Use単体を作成する場合 user = create(:user)
これでUserに紐づくGroupの作成・非作成を切り替える事が出来た。