Rails Diary

プログラミングの学習記録です。

FactoryBot 関連データの作成

FactoryBotにおけるアソシエーション

belongs_toとhas_many ※ 解釈が合っているか分からない
  • 所属(belongs_to)先を記載する場合はFactoryBotにassociation: author(associationは省略可)みたいに記載すればいい
  • has_manyの場合はassociationによる記載が使えないのでtraitやコールバックを用いて、後から関連データを入れ込む形
FactoryBot.define do
  factory :article do
    sequence(:title, "title_1")
    sequence(:slug, "slug_1")
    # belogns_toのリレーションのみ以下の記載が可能?
    category
    author
    # has_manyリレーションではassciationは使えないので、authorやtagの場合はtraitとコールバックであるafter(:create)を使う
  end

transientとコールバック after build

callback…特定の瞬間に呼び出されるメソッド

# articleのFactory続き
# traitを用いてhas_manyリレーションを入れ込む
trait :with_author do
  transient do
    sequence(:author_name, 'test_author_name_1')
    sequence(:tag_slug, 'test_author_slug_1')
  end 

  after(:build) do |article, evaluator|
    article.author = build(:author, name: evaluator.author_name, slug: evaluator.tag_slug)
  end
end
  • transientは実際に作成するデータと直接関係がない変数を定義する機能
  • モデルの属性以外のデータをファクトリに含めることができる
  • 作成時に挙動を変更するためのフラグや追加データとして利用する

■ after(:build)は何をしているのか。evaluatorって何者?

コールバックを使うことで生成したインスタンスがcreate,buildされたイベントの直後に自由にインスタンスを修正できる。

  • つまりafter(:build) do |article, evaluator|というブロックでは、コールバックによってarticleインスタンスが作られた後に、article.authorの値に修正が加えられている
after(:build) do |article, evaluator|
  article.author = build(:author, name: evaluator.author_name, slug: evaluator.tag_slug)
end

↑割と素直にコードを読んで良いんだなと思った。

  • after(:build) do |article|でarticleインスタンスが作られた後、ブロック内でarticle.authorの名前をtransientで生成したものに修正している
  • 第二引数のevaluatorを渡すことで、transientブロック内の変数にアクセスできる
    →この仕組みは、rails newコマンドでなぜ色んなファイルができるのか?みたいなレベルのお話になってくるので考えなくて良いとのこと◎

参考にしたサイト

FactoryGirlのtransientとtraitを活用する - Qiita

FactoryBot(旧FactoryGirl)で関連データを同時に生成する方法いろいろ - Qiita

factory_bot github アソシエーション