factory_bot 再入門
Railsを始めてはや数年、最初のころに factory_girl の勉強をして、それ以来必要に合わせてちょっと調べて終わりって感じで過ごしてきた。
最近Railsを始めた人に、「Railsチュートリアルとかeveryday railsとかやって、開発してるプロダクト見ると書き方が違ってる」って話を聞き、そう言えばその辺の知識って古いまま(と言っても2,3年前?)更新されてないな...と思って読み直すと結構知らなかったことが多かった。
なので、ざっとまとめてみる。
まとめる内容は全部ここに書いてるので、こちらを見るとよいかと!
attributes_for
これも地味に知らなかった。
# Returns a hash of attributes that can be used to build a User instance
attrs = attributes_for(:user)
Aliases
Factory に alias が付けれる
factory :user, aliases: [:author, :commenter] do
first_name "John"
last_name "Doe"
date_of_birth { 18.years.ago }
end
factory :post do
author
# instead of
# association :author, factory: :user
title "How to read a book effectively"
body "There are five steps involved."
end
factory :comment do
commenter
# instead of
# association :commenter, factory: :user
body "Great article!"
end
はい、知りませんでした...
ポリモーフィックとか使ってるのをちょいちょい見るので、これ使うとわかりやすくなるかな〜とか思ったり。
Transient Attributes
ちょいちょい見て、わかってるようで分かってなかった。
この例はわかりやすくて、理解できた。
factory :user do
transient do
rockstar true
upcased false
end
name { "John Doe#{" - Rockstar" if rockstar}" }
email { "#{name.downcase}@example.com" }
after(:create) do |user, evaluator|
user.name.upcase! if evaluator.upcased
end
end
create(:user, upcased: true).name
#=> "JOHN DOE - ROCKSTAR"
Inheritance
いつも trait を使ってたけど、こういうのもあるのか。一回で書けるって意味ではいいのかもな。
factory :post do
title "A title"
factory :approved_post do
approved true
end
end
approved_post = create(:approved_post)
approved_post.title # => "A title"
approved_post.approved # => true
factory :post do
title "A title"
end
factory :approved_post, parent: :post do
approved true
end
Associations
alias を使えばいいけど、こういう書き方もある。
factory :post do
# ...
association :author, factory: :user, last_name: "Writely"
end
Sequences
こうやって別個に定義できるってのは知らなかったな。
# Defines a new sequence
FactoryBot.define do
sequence :email do |n|
"person#{n}@example.com"
end
end
generate :email
# => "person1@example.com"
generate :email
# => "person2@example.com"
factory :invite do
invitee { generate(:email) }
end
factory :user do
email # Same as `email { generate(:email) }`
end
んで、aliasも定義できる
factory :user do
sequence(:email, 1000, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
end
# will increase value counter for :email which is shared by :sender and :receiver
generate(:sender)
Linting Factories
Lint ってよくあるけど、factory_bot でもあるって知らなかった。
「うるせー!」 って言いたくなることもあるけど(笑)
FactoryBot.lint
まとめ
これ以外にもいろいろ紹介されてたけど、基本的なところはこんなところかなと!
gemも定期的に見て、機能とか確認していかないとダメだなというのが今回の気付き!