カテゴリー:
Rails
タグ:
 Rails STI polymorphic

このエントリーをはてなブックマークに追加
更新日時:
2014年03月16日(日)
作成日時:
2014年03月15日(土)

前の記事 / 次の記事

とりあえずメモ。

環境: Rails4.0.1

Polymorphic
STI

PolymorphicもSTIもいずれもモデルをDRYにする仕組みなんだけど、
この両方を組み合わせて使うとバグる。

自分にとって都合が悪いだけで
そもそも敢えてそういう仕様なのかも知れないけど

っていうかやっぱそういう仕様だった。
Polymorphic Associations

具体的には次のような現象が起こる。

class Catalog< ActiveRecord::Base
  belongs_to :resouce, polymorphic: true
end

class Book < ActiveRecord::Base
end

class Magazine < Book
  has_many :catalogs, as: :resource
end
class Paperback < Book
  has_many :catalogs, as: :resource
end

みたいなモデルを定義した時、次のようになる

magazine = Magazine.new
catalog = Catalog.new
catalog.resource = magazine

catalog.resource_type #=> "Book"

"Magazine"になって欲しい。
Polymorphic Associationsによればresource_type= にあたるメソッドを
オーバーライドせよということなので言われた通りにする。

class Catalog< ActiveRecord::Base
  belongs_to :resouce, polymorphic: true

  def resource_type=(klass)
    super(klass.to_s.classify.constantize.base_class.to_s)
  end
end

とオーバーライドしたら"Magazine"になるようになるのかと思いきやならなくて、
更にゲッターもオーバーライドしたら"Magazine"になった。

class Catalog< ActiveRecord::Base
  belongs_to :resouce, polymorphic: true

  def resource_type
    resource.class.name
  end

  def resource_type=(klass)
    super(klass.to_s.classify.constantize.base_class.to_s)
  end
end

ただ、ゲッターをオーバーライドした時に他に影響がないのかは検証してないので分からない。

ちなみにPolymorphic Associationsを見るまでは、
セッターのオーバーライドを

class Catalog< ActiveRecord::Base
  belongs_to :resouce, polymorphic: true

  def resource_type
    resource.class.name
  end

  def resource_type=(klass)
    self[:resource_type] = resource.class.name
  end
end

として動かしてみたんだけど、これはバグった。