This project is archived and is in readonly mode.
Problem with has_many :through and alternate keys
-
Reto
- Assigned user set to Pratik
I have a similar problem here, but in my case its a has-many through has_many relation.
# Shift ---< ShiftTask >--- Task # Shift(group_id, name, ...) class Shift < ActiveRecord::Base has_many :shift_tasks, :primary_key => :group_id has_many :tasks, :through => :shift_tasks, :primary_key => :group_id end # ShiftTask(:id, :shift_id, :task_id ) class ShiftTask < ActiveRecord::Base belongs_to :shift, :primary_key => :group_id belongs_to :task, :primary_key => :group_id end # Task(group_id, name, ...) class Task < ActiveRecord::Base has_many :shift_tasks, :primary_key => :group_id has_many :shifts, :through => :shift_tasks, :primary_key => :group_id endThe attached patch fixes the problem in my case (based on 2.3.4). Please be aware that this my first A::R patch, I'm not sure what other things might break because of it. I've run the tests and they look good and well. I've currently lack the time and skills to write dedicated tests for this case. But if somebody can tell me that my approach is the right way to go, I'm willing to invest some time into unit tests.
One note about the patch. I've changed the owner_quoted_id of has_many_association because I think the usage of 'quote_value' is not correct there. Quote Value is implemented in ActiveRecord::Base, not in the association Proxy Class. But I'm not sure if this is only true for :through associations. In any case, the modified method could also be moved to the sub-class HasManyThroughAssociation, it works there as well.
Pratik: I've added you to the CC because you appear to be involved in all the parts which were changed. Especially you added an empty method called 'through_reflection_primary_key_name', which sounds like exactly what I've been looking for :).
Cheers,
Reto
-- SQL w/o Patch: SELECT `tasks`.* FROM `tasks` INNER JOIN `shift_tasks` ON `tasks`.id = `shift_tasks`.task_id WHERE ((`shift_tasks`.shift_id = 9)) ORDER BY position ASC -- correct shift_id is 1 SQL w/ Patch: SELECT `tasks`.* FROM `tasks` INNER JOIN `shift_tasks` ON `tasks`.group_id = `shift_tasks`.task_id WHERE ((`shift_tasks`.shift_id = 1)) ORDER BY position ASC -
Nick @ Reenhanced
Just wanted to update this with an independent observation.
I've run into the same issue and ended up writing the identical code provided by Reto to patch my codebase.Reto's code is a good way to fix this issue.
-
Mimosa
why not use change :foreign_key ?
has_many :friendships, :dependent => :destroy has_many :friends, :through => :friendships, :conditions => "state = 'accepted'" has_many :friends_activities, :class_name => 'Activity', :foreign_key => :user_id, :through => :friendships, :source => :friendSELECT `activities`.* FROM `activities` INNER JOIN `friendships` ON `activities`.user_id = `friendships`.friend_id WHERE `friendships`.user_id = 1 -
Mimosa
api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
:through
Specifies a Join Model through which to perform the query. ** Options for :class_name and :foreign_key are ignored **, as the association uses the source reflection. You can only use a :through query through a belongs_to has_one or has_many association on the join model. -
Mimosa
Options for :class_name and :foreign_key are ignored
-
John Woods
- Tag changed from 2.3.2, alternate_key, associations, has_many_through, primary_key to 2.3.2, 3.0.0, alternate_key, associations, has_many_through, primary_key
Rails 3.0 seems to have the same problem. Reto's patch doesn't work on 3.0, but you can make the same change by hand in /activerecord-3.0.0/lib/active_record/associations/through_association_scope.rb (line 56). It seems to work fine, now, but I wish this would get patched in rails.
-
Gustavo Gama
Here's an updated (activerecord-3.0.3) and slightly modified (reuses the :primary_key option from the 'source' reflection) version of Reto's patch.
-
Jon Leighton
- Assigned user changed from Pratik to Aaron Patterson
The attached patch fixes this (and a couple of related issues), with tests.
Note that I have consolidated
construct_owner_attributesandconstruct_quoted_owner_attributesas there is now no need for them to be separate since the recent arel refactoring ofconstruct_conditions.[This is actually already fixed in my nested :through patch (#1152), though it's of course always good to have these independent tests to guard against regressions.]
-
Jon Leighton
- Tag set to patch
-
Alex Neth
I'm having this issue with a non-"wierd legacy database schema". I am storing facebook friendships and the join table has a friend_facebook_uid property which references the user's facebook_uid:
class User
has_many :facebook_friendships has_many :facebook_friends, :through => :facebook_friendships, :class_name => 'User', :source => :friend ...class FacebookFriendshp
belongs_to :friend, :class_name => 'User', :foreign_key => 'friend_facebook_uid', :primary_key => 'facebook_uid' ...user.facebook_friendships works properly
user.facebook_friends is always empty because it tries to join on the user.id column, ignoring the primary_key parameter.These patches do not work for me - they change
SELECT "users".* FROM "users" INNER JOIN "facebook_friendships" ON "users".id = "facebook_friendships".friend_facebook_uid WHERE (("facebook_friendships".user_id = 11))
to
SELECT "users".* FROM "users" INNER JOIN "facebook_friendships" ON "users".id = "facebook_friendships".friend_facebook_uid WHERE (("facebook_friendships".user_id = '542552176'))
The first patch does not even seem to be executed. Argh.
-
Jon Leighton
Alex, have you tried with the patch I just uploaded? That should fix it - the test 'test_has_many_through_with_custom_primary_key_on_belongs_to_source' is targeting the exact scenario you've supplied.
-
Repository
- State changed from new to resolved
(from [14b880fd035fcdf807051398674c9aa89bd3b4d3]) Fix various issues with the :primary_key option in :through associations [#2421 state:resolved] https://github.com/rails/rails/commit/14b880fd035fcdf807051398674c9...
-
John Woods
Has this problem recurred? I'm seeing it again with the 3.1beta I just pulled from git.
-
John Woods
Okay, a bit more information. I have:
class Phenotype has_many :observations has_many :genes, :through => :observations end class Observation belongs_to :gene, :primary_key => :entrez_id endIt used to be that when I did
Phenotype.find(48291).gene_ids, it would give me theentrez_idattribute rather than the primary keys. This makes sense. I don't useidfor anything at all, which is why I setentrez_idas the primary. Unfortunately, in the current beta,gene_idsreturns the:idattribute on each gene.There are obvious workarounds, but this is obnoxious, and it can't be the correct behavior.
-
Jon Leighton
Hi John,
What you've reported sounds like a slightly different thing. I've opened a ticket at https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets... and will look into it.
Jon
-
Roland Pallai
Seems like this problem recurred on 2.3.11. It has been worked for a while on 2.3 AFAIK.
I've same models as Uwe Hees, his description perfectly matches with my problem.
-
Anthony Eden
It looks like this issue has come back in the 3.0.6 (and likely 3.0.5 and possibly earlier versions). I tried to cherry pick just this commit into a branch based on the v3.0.6 tag, but there are conflicts so I'm going to give up for now and just work around it.
-
Jon Leighton
This fix was never backported to 3-0-stable.
I have just done that: https://github.com/rails/rails/commit/9f5ab9a9ff3c9efe4126cf00dc69e...
It won't be backported to 2.3 - that branch is no longer being maintained.
