This project is archived and is in readonly mode.
belongs to association eager/pre- load fails when foreign key is same as association name
Reported by Minh Tran | March 9th, 2009 @ 11:22 PM | in 2.x
There is a subtle bug in the association preload code that causes eager loading not to work when the foreign key name is the same as the association name. For example,
belongs_to :created_by, :class => 'Person', :foreign_key => 'created_by'
Attached is a diff with a test case that will reveal the problem, as well as a two-line fix for it. The problem exists in 2.2.2 and AFAIK, 2.3 as well.
To elaborate, the problem occurs in "association_preload.rb" in method preload_belongs_to_association(). The id/key is obtained by doing:
record.send(primary_key_name)
However, in the case where the association name is the same as the foreign key, this will return the associated object, not the numeric id. Accessing the key/id with [ ] (square brackets) instead of send() will fix the problem.
This issue does not seem to exist with the other associations because they use construct_id_map(), which accesses the numeric id with [] already.
In the attached patch, the test case I wrote is quite simple. If eager loading worked (i.e. find() with :include), then the number of generated queries should be small.
For your reference, the failure output for the test case without the two-line fix would be:
1) Failure:
test_preload_belongs_to_with_foreign_key_name_same_as_association_name(EagerAssociationTest)
[./test/cases/../../lib/active_record/test_case.rb:31:in `assert_queries'
./test/cases/associations/eager_test.rb:785:in `test_preload_belongs_to_with_foreign_key_name_same_as_association_name'
./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `__send__'
./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `run']:
4 instead of 2 queries were executed.
Queries:
SELECT * FROM `funny_jokes` WHERE (created_by IS NOT NULL)
SELECT * FROM `people` WHERE (`people`.`id` = 2)
SELECT * FROM `people` WHERE (`people`.`id` = 1)
SELECT * FROM `people` WHERE (`people`.`id` IN (0,0)) .
<2> expected but was
<4>.
2017 tests, 6552 assertions, 1 failures, 0 errors
Comments and changes to this ticket
-
David Trasbo April 15th, 2010 @ 08:04 PM
- Assigned user set to Ryan Bigg
Giving a column and an association the same name is bound to cause trouble. Rails doesn't and shouldn't try to support doing things like this. Rename the column
created_by_id
, e.g. This ticket can be marked as invalid. -
David Trasbo April 15th, 2010 @ 08:04 PM
Giving a column and an association the same name is bound to cause trouble. Rails doesn't and shouldn't try to support doing things like this. Rename the column
created_by_id
, e.g. This ticket can be marked as invalid. -
Ryan Bigg April 15th, 2010 @ 10:26 PM
- State changed from new to invalid
Yup, never give your association the name of the foreign key, always give the foreign_key an _id suffix.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>