This project is archived and is in readonly mode.
HABTM Relationships Fail When Join Table has Primary Key
Reported by Jaime Bellmyer | February 25th, 2009 @ 06:49 AM | in 2.x
has_and_belongs_to_many relationships fail in an unexpected way when the join table has a primary key with the same name as a column in the associated table. The most common example is when the join table is created by migration without including the :id => false option, like so:
create_table :developers_projects do |t|
t.integer :developer_id
t.integer :project_id
end
The results are problematic. ActiveRecord takes any non-foreign-key columns in the join table, and fills them with values from the associated table. Therefore, ActiveRecord tries to forcibly assign the id of the join record to be the same as the id of the associated table. That's why, in the example above, you can only add a project to one developer.
My included patch excludes the join table primary key from being overridden, if it exists. It also includes the relevant test in has_and_belongs_to_many_associations_test.rb, called test_adding_a_collection_when_join_table_has_primary_key.
The result is that habtm join tables work as expected. Some may make the argument that join tables shouldn't have primary keys. While it's true join tables almost never need them, they shouldn't become a liability that appears only after you've added several records.
Comments and changes to this ticket
-
Jaime Bellmyer February 25th, 2009 @ 05:15 PM
- Tag changed from activerecord, duplicate, has_and_belongs_to_many, join_table, primary_key to activerecord, duplicate, has_and_belongs_to_many, join_table, patch, primary_key
After re-reading the ActiveRecord::Associations::ClassMethods docs, a new solution comes to mind. We're telling people in the docs not to have a primary key on the join table. Maybe instead of allowing primary keys to work error-free, we should raise an exception when the association is first made. This way having a primary key in your join table will fail right away, fail loudly, and with an error message that can be easily understood/researched.
If this is the better way to go, I can certainly implement it. Feedback is greatly appreciated.
-
Jaime Bellmyer February 26th, 2009 @ 04:54 PM
Can somebody with permissions please kill this ticket? I recently learned that this solution is not what the rails community wants. It's based on the legacy use of habtm before has_many :through came around. Now the use of habtm join tables is deprecated for anything fancy.
Still, we still have the problem of cryptic failure when the habtm join table contains a primary key. So I've created a different solution in ticket #2086 that raises an exception with a clear explanation.
-
Pratik March 9th, 2009 @ 01:34 PM
- Assigned user set to Pratik
- State changed from new to invalid
- Title changed from [PATCH] HABTM Relationships Fail When Join Table has Primary Key to HABTM Relationships Fail When Join Table has Primary Key
-
Reto July 16th, 2009 @ 10:25 AM
Sorry for waking up this old ticket, but I almost shoot my foot due to this problem today.
In my opinion the documentation doesn't stress this problem enough, it says:
'The join table should not have a primary key or a model associated with it. You must manually generate the join table with a migration such as this:'[0]this even suggests that it is possible (technically), but one 'should not' use a primary key. But it is not possible and it reveals this ugly bug.
Would it possible to add a clear note about that problem in the documentation?
[0] http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassM...
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>
People watching this ticket
Attachments
Referenced by
- 2086 [PATCH] Primary key on HABTM join table now raises an exception This patch replaces my earlier attempt to solve the probl...