STI is not working as I think it should under certain conditions.
The models (simplified):
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
Schema (simplified):
create_table "specs", force: :cascade do |t|
t.string "type", null: false
t.bigint "order_item_id", null: false
...
end
I'm using ActiveRecord::Associations::Preloader
to avoid n+1 problems in my GraphQL server. I've started getting some STI errors.
From a console, this works fine and returns a FooSpec
or BarSpec
:
Order.includes(items: :spec).first.items.first.spec
Same with this:
Order.includes(:items).first.items.includes(:spec).first.spec
And this too:
ActiveRecord::Associations::Preloader.new
.preload(Order.all, :items).first.owners.first.items.first.spec
However, this:
ActiveRecord::Associations::Preloader.new.preload(Order.all, items: :spec)
And this:
ActiveRecord::Associations::Preloader.new
.preload(Order.all.map{|o| o.items}.flatten, :spec)
Raise an error:
ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass: 'FooSpec'. This error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this column if you didn't intend it to be used for storing the inheritance class or overwrite Spec.inheritance_column to use another column for that information.
Sometimes I'm getting a slightly different error from the app but I cannot reproduce it in the console:
ActiveRecord::SubclassNotFound (Invalid single-table inheritance type: FooSpec is not a subclass of Spec)
Hmm...as you can see, FooSpec
is most definitely a subclass of Spec
. These errors usually mean you used type
as an attribute and did not tell ActiveRecord it's not an STI discriminator. That's not the case here. Ideas?