はじめに
rspecでモデルスペックを作成してるときにhas_many_throughのアソシエーションを持ったfactoryを作成しようとして作成の仕方がわからずかなりハマったので備忘録としてまとめます
テーブル構造
models/article.rb
class Article < ApplicationRecord
has_many :article_categories
has_many :categories, through: :article_categories
validates :title, presence: true
validates :body, presence: true
validate :select_categories
def select_categories
errors.add(:article_categories, 'を1つ以上選択してください') if article_categories.size.zero?
end
end
models/category.rb
class Category < ApplicationRecord
has_many :article_categories
has_many :articles, through: :article_categories
end
article_category.rb
class ArticleCategory < ApplicationRecord
belongs_to :article
belongs_to :category
end
今回はarticleとcategoryが多対多の関連を持っており、さらにarticleは作成する際1つ以上のcategoryをもつ必要のあるバリデーションが存在するような状況です
factoryの作成
spec/factories/articles.rb
FactoryBot.define do
factory :article do
title { 'タイトル' }
body { 'テキストテキストテキストテキストテキスト' }
after(:build) do |article|
category = create(:category)
article.article_categories << build(:article_category, article: article, category: category)
end
end
end
spec/factories/categories.rb
FactoryBot.define do
factory :category do
name { 'カテゴリー名' }
end
end
spec/factories/article_categories.rb
FactoryBot.define do
factory :article_category do
article
category
end
end
上記のように記述することでarticle作成と同時に関連テーブルまで作成し、バリデーションを通過させることができます
テスト結果
spec/models/article_spec.rb
require 'rails_helper'
RSpec.describe Article, type: :model do
it "有効なarticleを生成できる" do
expect(create(:article)).to be_valid
end
end
$ rspec --example '有効なarticleを生成できる'
.
Finished in 0.03327 seconds (files took 2.8 seconds to load)
1 example, 0 failures
無事テストが通ることが確認できました!
factory_girlからfactory_botに名前変更してからfactory_botの記事がほとんど見つからなくて泣いてますw
これ以外にもっと良いやり方を知ってる方いたらコメントなどで教えていただけると嬉しいです!
参考文献
factory_bot公式ドキュメント GETTING_STARTED.md
stackoverflow