【发布时间】:2017-07-08 17:50:04
【问题描述】:
STI 在某些情况下无法正常工作。
模型(简化):
class Order < ApplicationRecord
has_many :items, class_name: 'OrderItem', inverse_of: :order
end
class OrderItem < ApplicationRecord
belongs_to :order, inverse_of: :items
has_one :spec, inverse_of: :order_item
end
class Spec < ApplicationRecord
belongs_to :order_item, inverse_of: :spec
end
class FooSpec < Spec
end
class BarSpec < Spec
end
架构(简化):
create_table "specs", force: :cascade do |t|
t.string "type", null: false
t.bigint "order_item_id", null: false
...
end
我正在使用ActiveRecord::Associations::Preloader 来避免我的 GraphQL 服务器中出现 n+1 问题。我开始遇到一些 STI 错误。
从控制台,这可以正常工作并返回 FooSpec 或 BarSpec:
Order.includes(items: :spec).first.items.first.spec
与此相同:
Order.includes(:items).first.items.includes(:spec).first.spec
还有这个:
ActiveRecord::Associations::Preloader.new
.preload(Order.all, :items).first.owners.first.items.first.spec
但是,这个:
ActiveRecord::Associations::Preloader.new.preload(Order.all, items: :spec)
还有这个:
ActiveRecord::Associations::Preloader.new
.preload(Order.all.map{|o| o.items}.flatten, :spec)
引发错误:
ActiveRecord::SubclassNotFound:单表继承机制 未能找到子类:'FooSpec'。引发此错误 因为列'type'保留用于存储类,以防万一 遗产。如果您不打算将其重命名,请重命名此列 用于存储继承类或覆盖 Spec.inheritance_column 为该信息使用另一列。
有时我会从应用程序中得到一个稍微不同的错误,但我无法在控制台中重现它:
ActiveRecord::SubclassNotFound(无效的单表继承类型: FooSpec 不是 Spec 的子类)
嗯...如您所见,FooSpec 绝对是Spec 的子类。这些错误通常意味着您使用type 作为属性并且没有告诉ActiveRecord 它不是STI 鉴别器。这不是这里的情况。想法?
【问题讨论】:
标签: ruby-on-rails ruby activerecord