开发者

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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜