Can anyone explain why line 1372 of lib/active_record/
associations.rb performs a String equality check as opposed to a more
conventional Object equality check:
return nil if record.id.to_s != join.parent.record_id(row).to_s or
row[join.aliased_primary_key].nil?
I stumbled across this when attempting to monkey patch the Oracle
Adapter as I noticed that on some occasions columns were incorrectly
interpreted as Floats instead of Integer.
I stumbled across this when attempting to monkey patch the Oracle
Adapter as I noticed that on some occasions columns were incorrectly
interpreted as Floats instead of Integer.
Because of the thing where ids are sometimes integers (eg User.find
123) and sometimes strings.
Perhaps some more context would help. Executing the following
triggers this code:
Customer.find(1, :include => :orders)
The include clause adds a join to the resulting SQL so that the
Customer and it’s related Orders can be retrieved via a single query.
This code comes into play after the query executes and acts on the
result set; it appears to be verifying the child (Order) has a
matching foreign key to the parent (Customer) in the result set.
So here’s my original question with some points/Q’s thrown in:
The verification appears to be redundant as the query contains a
where clause limiting the result set to the parent id.
It uses an unconventional equality check via String conversion,
why (as per my original question)?
Invoking record.id causes adapter specific logic to execute that
may convert the type of the value to some other type, however
join.parent.record_id(row) does not perform that same logic - I
suspect this is a defect? As a consequence of this I’ve seen cases
where 1 != 1.0 (for instance)
This code comes into play after the query executes and acts on the
result set; it appears to be verifying the child (Order) has a
matching foreign key to the parent (Customer) in the result set.
So here’s my original question with some points/Q’s thrown in:
The verification appears to be redundant as the query contains a
where clause limiting the result set to the parent id.
In your case yes: there is only one parent, but not in the case when
you’ve got Customer.find(1,2,3, :include => :orders) or Customer.find
(1, :include => {:orders => :products})
It uses an unconventional equality check via String conversion,
why (as per my original question)?
Invoking record.id causes adapter specific logic to execute that
may convert the type of the value to some other type, however
join.parent.record_id(row) does not perform that same logic - I
suspect this is a defect? As a consequence of this I’ve seen cases
where 1 != 1.0 (for instance)
The main thing is to avoid instatiating more AR objects than are
needed, the way :include works more rows are returned than there are
objects emerging on the other end, eg if the customer has 10 orders,
you don’t want to instatiate the customer 10 times. I expect 2. is an
attempt to make this work most of the time without the adapter
specific logic from record.id.
The short answer is that :include is usually quite overcomplicated
(as someone who also once read through the JoinBase / JoinDependency
code you have my sympathy). There is a simple solution in the
pipeline, but it’s not quite ready yet.
Fred
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.