FactoryBotでポリモーフィックなアソシエーションを生成する


はじめに

FactoryBotを書いてて、ポリモーフィック関連を自動生成するにはどうしたらいいんじゃ!
と思って調べたので、忘備録です。

やりたいこと

例えばツイッターのようなアプリを作ることを考えて、Postテーブルを作ることにします。Postテーブルには投稿主を表すpostable_idがあるとします。
投稿できるのは、一般のUserの他に別テーブルで管理されてるCompanyも投稿できるようにしたとしましょう。すなわちUserとCompanyはPostとポリモーフィックな関係で結ばれています。

User ----|
         |---- Post
Company--|

この時、postを生成するのと同時にuserやcompanyをFactoryBotで自動的に生成する方法を説明します。

解決

では 早速コードをみてみましょう。
まずは、デフォルトで用意されてるかもしれませんが、userとcompanyを作成するファクトリを用意します。

factories/users.rb
FactoryBot.define do
  factory :user, class: 'User' do
   name { 'test' }
  end
end
factories/companies.rb
FactoryBot.define do
  factory :company, class: 'Company' do
   name { 'test' }
  end
end

上記は特になんの変哲のないファクトリーです。specにcreate(:user)みたく書けばuserを作成できるでしょう。
続いてPostのファクトリーは以下のようになります。

factories/posts.rb
# userのpostを生成(postと一緒にuserができる)
FactoryBot.define do
  factory :user_post, class: 'Post' do
    postable_type { 'User' }
    #ポリモーフィック関連の名前を指定して、userを生成するfactorを呼ぶ
    association :postable, factory: :user
  end

# companyのpostを生成(postと一緒にcomapnayができる)
  factory :company_post, class: 'Post' do
    postable_type { 'Company' }
    #ポリモーフィック関連の名前を指定して、userを生成するfactorを呼ぶ
    association :postable, factory: :company
  end
end

肝はassociationでfactoryを指定することです。これによってuserかcompanyを自動で作成してくれます。
もちろんspecではcreate(:user_post)で問題ありません。
便利なので是非ご活用ください!