让我们看看我们有多态表
class DB::Document < ActiveRecord::Base
# documentable_type, documentable_id
belongs_to :documentable, polymorphic: true
end
class DB::Ticket < ActiveRecord::Base
has_one :document, as: :documentable
def self.find_sti_class(type_name)
ActiveSupport::Dependencies.constantize("DB::Ticket::#{sti_type_for(type_name)}")
end
self.inheritance_column = :type
self.store_full_sti_class = false
def self.sti_name
self.to_s.split('::').last
end
end
class DB::Ticket::Train < DB::Ticket
end
class Ticket::Airplain < DB::Ticket
end
当我们设置关联时:
doc = Document.new
doc.documentable = DB::Ticket::Train.first! # docuementable_type will be 'DB::Ticket'
当我们预加载多态关联时:
DB::Ticket.where(id: [1,2]).preload(:document).to_a
# SELECT * FROM documents WHERE documentable_id IN (1,2) AND documentable_type = 'Ticket'
我认为它是因为在association.writer上它使用了base_class的name
module ActiveRecord
# = Active Record Belongs To Polymorphic Association
module Associations
class BelongsToPolymorphicAssociation < BelongsToAssociation #:nodoc:
...
def replace_keys(record)
super
owner[reflection.foreign_type] = record.class.base_class.name
end
...
end
end
end
并在预加载时使用base_class的sti_name
module ActiveRecord
module Associations
class Preloader
class Association #:nodoc:
...
def build_scope
scope = klass.unscoped
...
if options[:as]
scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
end
...
end
...
end
end
end
end
为什么sql for preload会生成错误的documentable_type? 这是我在使用STI / polymorhic或ActiveRecord错误时的错误吗?