はじめに
Factorybotのコード内に transient
という定義を見かけました。 初めて見かけた属性だったので調べてみました。
transient属性とは?
factory_bot gemのGETTING_STARTEDドキュメントには以下のように定義されていた。
Transient attributes are attributes only available within the factory definition, and not set on the object being built. This allows for more complex logic inside factories.
「一時的属性」とは、ファクトリーの定義内でのみ利用可能な属性であり、構築されるオブジェクトには設定されません。これにより、ファクトリー内でより複雑なロジックを実装できます。
とのことで、モデルに定義された属性とは別にファクトリー内の一時的な変数のように利用できる属性のようです。
transient属性を使ったよくありそうな実装例
フラグの定義
transient
属性にフラグを定義し、他の属性からそのフラグを参照することで挙動を変えるパターン。ファクトリーでcreateするときに、フラグの値を渡すことで任意のデータを登録するようにできるようになる。
factory :item do
transient do
secret { false }
end
name { "#{"[secret] "if secret}Item Name" }
end
[3] pry(#<RSpec::ExampleGroups::Items::GETItems>)> create(:item).name
=> "Item Name"
[4] pry(#<RSpec::ExampleGroups::Items::GETItems>)> create(:item, secret: true).name
=> "[secret] Item Name"
回数の定義
transient
属性で回数を定義し、複数データを作成する際の初期値として利用します。回数を初期値として設定しつつ、状況に応じて変えたい場合には有効です。
factory :category do
transient do
article_count { 5 }
end
trait :with_articles do
after(:create) do |category, evaluator|
create_list(:article, evaluator.article_count, category: category)
end
end
end
# カテゴリー作成時に5個の記事も合わせて作成される
create(:category, :with_articles)
# カテゴリー作成時に10個の記事も合わせて作成される
create(:category, :with_articles, article_count: 10)
まとめ
ファクトリー内だけで利用できる一時的な属性の trasient
というのを知りました。このtransient
属性をtraitや他属性と組み合わせることで、細かい条件でデータ作成ができるようになり便利そうです。