Posted at

【Rails】factory_botでassociation関係のあるモデルの作り方


Introduction

Railsでhas_manybelongs_toなどのアソシエーションの関係のあるモデルをfactory_botで生成する方法のメモ。

いままでずっと、


spec/factories/factory.rb

FactoryBot.define do

factory :author do
name { "Author Name" }
end

factory :book do
author_id { 1 }
title { "Book Title" }
end
end



spec/system/xxxxx_spec.rb

# ~~~ #

background do
@author = create(:author)
@book1 = create(:book, author_id: @author.id, title: "book 1")
@book2 = create(:book, author_id: @author.id, title: "book 2")
@book3 = create(:book, author_id: @author.id, title: "book 3")
@book4 = create(:book, author_id: @author.id, title: "book 4")
@book5 = create(:book, author_id: @author.id, title: "book 5")
end
# ~~~ #

みたいな書き方をしてしまっていたのですが、それぞれの項目は連番とかでよいテストではもっといい方法がありました...


前提

Author has_many Books (Authorモデルは0以上のBookモデルを子に持つ)

Book belongs_to Author (Bookモデルは1つのAuthorモデルを親に持つ)

Author

id:integer

name:string

Book

id:integer

author_id:integer

title:string

ちなみにselenium+rspec+capybaraでsystem testをするのを想定してます。

Rails on Dockerにて、Headless ChromeでSystem Testをやってみた。 - Qiita

また、使用しているfactory_botのversionは5.0.2です。


Solusion


spec/factories/factory.rb

FactoryBot.define do

factory :author do
name { "Author Name" }

factory :author_with_books do
transient do
books_count { 5 }
end
after(:create) do |author, evaluator|
create_list(:book, evaluator.books_count, author: author)
end
end
end

factory :book do
title { generate(:book_title) }
end

sequence :book_title do |n|
"Book Title #{n}"
end
end


これで



  • create(:author)Bookを持たないAuthor


  • create(:author_with_books)Bookを5つ持つAuthor

が作れるようになりました。create(:author_with_books)でできるBookの数は7行目のbooks_countで変更できます。

また、Booktitlegenerate(:book_title)としています。これは19行目のsequence :book_titleを呼び出していますが、sequenceは呼び出されるたびにnがカウントアップするため、Book Title 1, Book Title 2, ・・・、といったtitleBookオブジェクトが5つできることになります。


spec/system/xxxxx_spec.rb

# ~~~ #

background do
@author = create(:author_with_books)
end
# ~~~ #

テストシナリオファイル側では1行で1つのAuthorオブジェクトとそれに紐づく5つのBookオブジェクトを扱えるようになります。Bookオブジェクトは、@author.books[i]の形でアクセスすることができます。


Conclusion

テストシナリオファイルがかなりスッキリしました。

Getting Started見る限り、まだまだ知らない便利な書き方がありそう。ちゃんと読まねば。


Reference