FactoryGirl で多対多のアソシエーションをつくる
FactoryGirl の公式 README 読んでも多対多のアソシエーションをつくる書き方が分からなくて、先日やっと分かったのでメモしておきます。
使用しているバージョンは下記のとおりです。
登場モデル
例として、Video
, Tag
, Tagging
が登場します。文字だけじゃ分かりにくいから graph-easy さんの出番ですね。
+-------+ 1:n +---------+ n:1 +-----+ | Video | <=====> | Tagging | <=====> | Tag | +-------+ +---------+ +-----+
- Video has_many taggings
- Video has_many tags, through taggings
- Tag has_many taggings
- Tag has_many videos, through taggings
- Tagging belongs_to video
- Tagging belongs_to tags
FactoryGirl.define の中で多対多をつくる
FactoryGirl.define の中で多対多をつくるときは下記のような感じ。
FactoryGirl.define do factory :tag do name '喪服' end factory :video do title 'あなた、許して' after(:create) do |video| create(:tag, videos: [video]) end end end
もう少し実践的に書くと、実際のテストにはアソシエーションがない場合の video も必要なので、下記のようにネストさせたりしています。あと、シーケンス使ったりとか。
FactoryGirl.define do factory :tag do sequence(:name) { |n| "喪服#{n}" } end factory :video do sequence(:title) { |n| "あなた、許して#{n}" } factory :video_with_tags do after(:create) do |video| create(:tag, videos: [video]) end end end end
テストの中で多対多をつくる
多対多の関連をテストの中でつくりたいときもありますよね。下記のように書きます。
let(:tag1) { create(:tag) } let(:tag2) { create(:tag) } let!(:video) { create(:video, tags: [tag1, tag2]) } before do visit videos_path end it '動画に関連するタグが表示される' do expect(page).to have_css(".tag", text: tag1.name) end
おまけ - FactoryGirl. を省略する
なお、spec/spec_helper.rb に下記を記述しておくと、
RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods end
毎回毎回 FactoryGirl.create(:video)
と書かずに create(:video)
でいけるよと、最近 @hsbt さんに教えていただきました。べんり〜
参考
以上です。
factory_girl は公式 README がすごく丁寧に書かれているので、多対多以外のことは、基本的にそちらを参照すればよいと思うのですが、とりあえず基本的なことを日本語で読みたい、という方には下記の記事がオススメです(下記記事にも多対多の書き方が載っていますが、今回紹介している書き方とは異なります)
ではでは。