The has_many :through association where the
through association is a belongs_to, (a
feature introduced by #323 has_many :through => belongs_to_association bug) can generate SQL queries with an unquoted
primary key value.
The following example will fail when the has_many
:through association is used and Ocean's primary key value
is something that needs quoting.
class Fisherman < ActiveRecord::Base
belongs_to :ocean
has_many :crabs, :through => :ocean
end
class Ocean < ActiveRecord::Base
# Ocean's primary key is e.g. a string
has_many :crabs
end
class Crab < ActiveRecord::Base; end
Here is an example of what this might yield:
>> f = Fisherman.first
=> #<Fisherman id: 2, ocean_id: "atlantic">
>> f.crabs
ActiveRecord::StatementInvalid: [...]
no such column: atlantic:
SELECT "crabs".* FROM "crabs"
INNER JOIN "oceans" ON "crabs".ocean_id = "oceans".id
WHERE (("oceans".id = atlantic))
The bug is in HasManyThroughAssociation's
construct_quoted_owner_attributes. It properly quotes
the primary key value for the two other types of has_many
:through, but not the belongs_to:
# Associate attributes pointing to owner, quoted.
def construct_quoted_owner_attributes(reflection)
if as = reflection.options[:as]
{ "#{as}_id" => owner_quoted_id,
"#{as}_type" => reflection.klass.quote_value(
@owner.class.base_class.name.to_s,
reflection.klass.columns_hash["#{as}_type"]) }
elsif reflection.macro == :belongs_to
{ reflection.klass.primary_key => @owner[reflection.primary_key_name] }
else
{ reflection.primary_key_name => owner_quoted_id }
end
end
This is clearly wrong as the method name and comment indicates
that it should quote the attributes. The code in question was
commited in
95e1cf4812.... I have attached a simple patch to add the needed
quoting.