rails: Join table cannot update or destroy throw error of no primary key
Steps to reproduce
Have models as follow:
class Event < ApplicationRecord
belongs_to :deal
has_many :events_users
has_many :users, through: :events_users
end
class Deal < ApplicationRecord
belongs_to :team
has_many :deals_users
has_many :users, through: :deals_users
has_many :events
end
class Team < ApplicationRecord
has_many :deals
has_many :team_users
has_many :users, through: :team_users
end
class User < ApplicationRecord
has_one :team, through: :team_user
has_one :team_user
has_and_belongs_to_many :deals
has_and_belongs_to_many :events
end
class EventsUser < ApplicationRecord
belongs_to :event
belongs_to :user
validates_uniqueness_of :event_id, scope: :user_id
enum status: [:pending, :accepted, :maybe, :rejected]
end
class DealsUser < ApplicationRecord
belongs_to :user
belongs_to :deal
validates_uniqueness_of :deal_id, scope: :user_id
end
class TeamUser < ApplicationRecord
belongs_to :user
belongs_to :team
validates_uniqueness_of :team_id, scope: :user_id
validates_uniqueness_of :user_id
end
Expected behavior
The join tables, EventsUser
, DealsUser
, TeamUser
can be updated or deleted.
Actual behavior
It can only be created, the update will throw
ActiveRecord::UnknownPrimaryKey: Unknown primary key for table events_users in model EventsUser.
Can not validate uniqueness for persisted record without primary key.
and destroy will throw
NoMethodError: undefined method `to_sym' for nil:NilClass
These following are my testing procedures in rails c
.
eu = EventsUser.first
eu.status = "maybe"
eu.save (throw update error)
eu.destroy (throw destroy error)
eu (it exists)
eu.status (return the status)
status
is an enum in model, and defined in migration as such:
t.integer :status, default: 0
System configuration
Rails version: Rails 5.0.0.rc1 Ruby version: ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
Reference
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 2
- Comments: 26 (8 by maintainers)
I’ve read the thread and I can’t wrap my head around the fact that
create_join_table
by default creates a join table with noprimary_key
and at the same time:How can both be true? Is using
create_join_table
something we should avoid? Or am I missing something here?It works if you use
dependent: :delete_all
instead of:destroy
I’m in Rails 5 in a new project and encountering this same issue. I echo @GomaaK’s confusion. I don’t have a model for these join tables; there’s nowhere to even stick
self.primary_key =
if I wanted to. What iscreate_join_table
good for if it can’t … be … used?It works if I remove
id: false
. I can work around the problem by testing uniqueness in the model, but it leaves me with a uselessid
field in a join table.Old thread but in case it helps… my understanding is that if you use
create_join_table
you should also be usinghas_and_belongs_to_many
, nothas_many through:
. This creates a simple bare join table with noid
, and you cannot work with those as objects directly.The problem is still actual If we have models/Page.rb
has_many :items, dependent: destroy has_many :page_items, through: :items
Page.last.destroy => PG::Error: ERROR: zero-length delimited identifier at or near “”“”
After being tired of these errors I just put a primary key on all my join tables
Having this issue on Rails 6.0.
What are best practices here and are there plans to fix the AR behavior with join tables? Ideally join tables would not need a primary
id
for thedependent: :destroy
option to be honored.I’m switching to manually
delete
-ing dependencies – is this the best option?Hi @batmanbury , Rails is looking for a primary key for deleting a record. Check this Rails take ID as default primary key and as it’s not present it gives a to_sym error for null class. For temporary basis, you can avoid this issue by mentioning primary_key in model as
self.primary_key = <column_name having uniq index>
or you need to add ID column in a table which will serve as a primary_key.
This solved my issue
Created a bug_report_template script for this issue; the behavior is not being reproduced by the script. Hopefully, it will help identify the difference that is causing the issue for @starkshaw and @ibussieres .
Script to reproduce the issue with join table update and delete