I have a problem where rails is adding unnecessary (I think) clauses to my belongs_to association - restricting on type even though my association is using a foreign key.
The STI setup looks like this:
class Foo < ActiveRecord::Base
belongs_to :apple
end
class Apple < Fruit
has_many :foos
end
So Foo
has an apple_id
column which links to the primary key column ID in fruits
, and Apple
is STI under Fruit
. I'm happy with all of this.
Now:
> Foo.joins(:apple).to_sql
SELECT "foos".* FROM "foos" INNER JOIN "fruits" ON "fruits"."id" =
"foos"."apple_id" AND "fruits"."type" IN ('Apple')
Why is rails adding AND "fruits"."type" IN ('Apple')
? It's a belongs_to using a primary key of the fruits
table, so the type part seems redundant. Can I stop rails from adding that part to the lookups and just get this:
SELECT "foos".* FROM "foos" INNER JOIN "fruits" ON "fruits"."id" =
"foos"."apple_id"
I know I could do belongs_to :apple, :class_name => "Fruit"
in Foo, but I want the objects to auto-become Apple
s when they're returned.
In case someone questions my motives... I want to do this because the type clause is messing up the query plan postgres chooses when I'm doing a query through fruits
to other tables (yes, I have an index on type
and even tried a multi-column one on [type,id]
). That's a little complicated / irrelevant to describe fully here.
Basically AM is adding the ('Apple') part because in order to respect the inheritance chain.
For example if you'd have
class GreenApple < Apple
end
You'll get.
Foo.joins(:apple).to_sql SELECT "foos".* FROM "foos" INNER JOIN "fruits" ON "fruits"."id" = "foos"."apple_id" AND "fruits"."type" IN ('Apple', 'GreenApple')
If for whatever reason you end up having on your fruits tabel a fruit with a referenced pk but with a different type you could end up instantiating a different kind of object without knowing it and after that things can go wrong without getting an exception.