upinetree's memo

Web系技術の話題や日常について。

FactoryGirlでファクトリ継承時、クラス指定を忘れて困った

困ったのでメモ。

次のようなSTIな感じのモデルがあるとき、ファクトリ側でも継承を使いたいなーと思うわけです。

モデル

class Post < ActiveRecord::Base
end

class PhotoPost < Post
  belongs_to :album
end

Factory

FactoryGirl.define do
  factory :post do
  end

  factory :photo_post, parent: :post do
    album
  end
end

photo_postをparentオプションでpostから継承した。でも、こう書いた場合albumなんて知らんと怒られる。

pry(main)> FactoryGirl.build(:photo_post)
NoMethodError: undefined method `album=' for #<Post:0x007f8e1b52ccd0>

なぜなら、photo_postは継承元(post)のインスタンスとして生成されるため。

albumの記述を削除して確認。

pry(main)> FactoryGirl.create(:photo_post).class
=> Post(id: integer, title: string, body: text, type: string, created_at: datetime, updated_at: datetime)

postにはalbumとの関連はないため、参照しようとして怒られていた。 これを回避するには、ファクトリ定義時にclassオプションを指定する。

  factory :photo_post, class: PhotoPost, parent: :post do
    album
  end

classオプションによりファクトリphoto_postがPhotoPostを生成することを教えられた。 これで、生成されるインスタンスはPhotoPostになる。

pry(main)> FactoryGirl.create(:photo_post).class
=> PhotoPost(id: integer, title: string, body: text, type: string, created_at: datetime, updated_at: datetime)

class指定忘れずにしようねというお話でした。