Can't destroy record in many-to-many relationship
I'm new to Rails, so I'm sure I've made a simple mistake.
I've set up a many-to-many relationship between two models: User
and Group
. They're connected through the junction model GroupMember
.
Here are my models (removed irrelevant stuff):
class User < ActiveRecord::Base
has_many :group_members
has_many :groups, :through => :group_members
end
class GroupMember < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
class Group < ActiveRecord::Base
has_many :group_members
has_many :users, :through => :group_members
end
The table for GroupMembers
contains additional information about the relationship, so I didn't use has_and_belongs_to_many
(as per the Rails "Active Record Associations" guide).
The problem I'm having is that I can't destroy a GroupMember
.
Here's the output from rails console:
irb(main):006:0> m = GroupMember.new
=> #<GroupMember group_id: nil, user_id: nil, active: nil, created_at: nil, updated_at: nil>
irb(main):007:0> m.group_id =1
=> 1
irb(main):008:0> m.user_id = 16
=> 16
irb(main):009:0> m.save
=> true
irb(main):010:0> m.destroy
NoMethodError: undefined method `eq' for nil:NilClass
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-3.0.4/lib/active_support/whiny_nil.rb:48:in `method_missing'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/persistence.rb:79:in `destroy'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/locking/optimistic.rb:110:in `destroy'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/callbacks.rb:260:in `destroy'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-3.0.4/lib/active_support/callbacks.rb:413:in `_run_destroy_callbacks'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4开发者_如何学Go/lib/active_record/callbacks.rb:260:in `destroy'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/transactions.rb:235:in `destroy'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/transactions.rb:292:in `with_transaction_returning_status'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in `transaction'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/transactions.rb:207:in `transaction'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/transactions.rb:290:in `with_transaction_returning_status'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.4/lib/active_record/transactions.rb:235:in `destroy'
from (irb):10
This is driving me crazy, so any help would be greatly appreciated.
When you switched from the HABTM relationship to a has_many :through relationship it looks like you may have forgotten to add back the id column. Active record needs GroupMember to have an id for .destroy to work like that.
Look for the :id => false
in your migration and get rid of it. then redo the migration.
Hope that helps.
I think your group_members table in the database doesnt have a primary key. Maybe you didnt set it up. So, when you create a new GroupMember object and save it, it will not have id. You cannot destroy an object without id(primary key).
I ran into the same problems you're describing and your post made me look further for a solution. This is what I found:
1- Get this composite primary keys library from http://compositekeys.rubyforge.org/ 2- Add it to your gem file 3- Add the following to GroupMember set_primary_keys [:user_id, :group_id]
- note set_primary_keys and not set_primary_key
this will return the right primary when you call GroupMember.primary_key when destroy looks for .primary_key , it'll now find it.
Try it in your console: gm = GroupMember.first gm.destroy
I hope this helps =)
If you are using associations and for whatever reason chose not to use Active Records default id, you can set the default id using "set_primary_key" so methods like find and destroy work properly.
class User < ActiveRecord::Base
set_primary_key :user_primary
has_many :group_members, :dependent => :destroy
has_many :groups, :through => :group_members
end
class GroupMember < ActiveRecord::Base
set_primary_key :group_member_primary
belongs_to :group
belongs_to :user
end
class Group < ActiveRecord::Base
set_primary_key :group_primary
has_many :group_members, :dependent => :destroy
has_many :users, :through => :group_members
end
Have you tried m.reload.destroy
instead of m.destroy
, to see what happens?
精彩评论