今回は、ファクトリーガールを使ってhas_one、has_many、polymorphic連想のデータを生成する方法について説明します。
has_one関連データの生成
has_one関連を設定するのは非常に簡単で、ファクトリー内で定義できます。 ファクトリー名がアソシエーション名と同じであれば、ファクトリー名を省略することができます。 たとえば:
FactoryBot.define do factory :story do # story attributes author endend
また、別のファクトリーを指定して属性を上書きすることもできます:
FactoryBot.define do factory :story do # story attributes association :author, factory: :user, first_name: "Jon" endend
関連を作成するための異なる戦略を指定することもできます:
association :author, factory: :user, strategy: :build
これではデータベースに関連オブジェクトを保存できないことに留意してください。
has_many 関連付けのデータを生成する
has_many 関連付けのデータを生成するのは、少し複雑です。 新しいファクトリーを定義し、after(:create)コールバックを使ってアソシエーションのリストを作成することができます。 この例でその方法を見てみましょう。
FactoryBot.define do # user factory without associated stories factory :user do # user attributes factory :user_with_stories do transient do stories_count 10 end after(:create) do |user, evaluator| create_list(:stories, evaluator.stories_count, user: user) end end endend
属性 stories_count は一時的なもので、ファクトリーの属性および評価器を経由したコールバックで使用できます。
create(:user_with_stories).stories.length # 10create(:user_with_stories, stories_count: 15).stories.length # 15
すべてのストーリーは一意の ID を持ちますが、他の属性を一意にするために、各ストーリーに対して異なる値を生成する必要があることに注意してください。
これを実現するには、例としてシーケンスを使用します:
FactoryBot.define do factory :story do # story attributes sequence(:title) { |n| "Title#{n}" } # Unique title for every story association :author, factory: :user, first_name: "Jon" endend
また、faker というユニークな値を生成するのに役立つ興味深い gem があります。
Polymorphic Association のデータを生成する
多相関連は少し混乱しやすいかもしれません。 この例で理解が深まれば幸いです。 多相関連を持つ次のクラスがあるとします。
class Profile belongs_to :profileable, polymorphic: trueendclass Account belongs_to :accountable, polymorphic: trueendclass User has_one :profile, as: :profileable has_one :account, as: :accountableend
多相モデルを持つモデルのファクトリーを作成する場合、単に after(:create) ブロックで多相モデルを作成し、多相可能を指定して、ファクトリーが対象とするモデルを指定するだけです。… 以上です!
この記事を読んでいただきありがとうございます。
Railsに関する興味深い記事をもっと読みたい場合は、ぜひニュースレターを購読してください!
同様の話題に興味がありますか? Rspec let vs before、Rspec Setup、FactoryGirl – create vs build vs buldstubbed の各項目について、ぜひご覧ください。