コード読むときのメモです。すみません
仕組み
モデルのインスタンスを new するところ
メソッド: ActiveRecord::Inheritance#new
ActiveRecord::Inheritance モジュールにて、レコードに対応するクラス名を取得していて subclass があれば subclass として new を、それ以外だったら普通に ActiveRecord::Base の new をしている
if subclass && subclass != self
subclass.new(*args, &block)
else
super
end
クラス名の決定
subclass_from_attributes
メソッド内で、レコードの inheritance_column
で指定される attributes の値を find_sti_class
に渡している
メソッド: ActiveRecord::Inheritance#subclass_from_attributes
subclass_name = attrs[inheritance_column] || attrs[inheritance_column.to_sym]
if subclass_name.present?
find_sti_class(subclass_name)
end
inheritance_column
は ModelSchema で定義していて (ActiveRecord::Base が include している)、 デフォルトでは "type" である
find_sti_class
メソッドでは、所謂 type を使って constantize までする。
メソッド: ActiveRecord::Inheritance
def find_sti_class(type_name)
type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
subclass = begin
if store_full_sti_class
ActiveSupport::Dependencies.constantize(type_name)
else
compute_type(type_name)
type_name を type_for_attribute で構築し直しているが、type_for_attribute が string じゃないことも一応あるのだろうか...
改造したいときは
カラムを変える
inheritance_column メソッドをオーバーライドすればよいはず
マッピングルールを変える
たとえば一般的なクラス名を string で入れておく使い方じゃなく、何か別の文字列を入れてクラス名にマッピングさせたいときは、 find_sti_class
をオーバーライドすることで実現できるらしいです
https://qiita.com/suusan2go/items/6da23826523744a74ba3