Не може да унищожи запис във връзка много към много

Нов съм в Rails, така че съм сигурен, че съм направил проста грешка.

Настроих връзка много към много между два модела: User и Group. Те са свързани чрез модела на кръстовището GroupMember.

Ето моите модели (премахнати неподходящи неща):

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

Таблицата за GroupMembers съдържа допълнителна информация за връзката, така че не използвах has_and_belongs_to_many (съгласно ръководството на Rails „Active Record Associations“).

Проблемът, който имам е, че не мога да унищожа GroupMember.

Ето изхода от rails конзолата:

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/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

Това ме подлудява, така че всяка помощ ще бъде много оценена.


person Dan Martens    schedule 22.02.2011    source източник
comment
имате ли обратни извиквания преди/след в модела GroupMember? Изглежда, че това е точното място на вашия ужас   -  person fl00r    schedule 23.02.2011
comment
не, моят модел GroupMember всъщност е само тези 2 реда по-горе   -  person Dan Martens    schedule 23.02.2011
comment
Какво получавате, когато направите GroupMember.primary_key в конзолата?   -  person zetetic    schedule 23.02.2011


Отговори (5)


Когато сте превключили от връзката HABTM към връзка has_many :through, изглежда, че може да сте забравили да добавите обратно колоната id. Активният запис се нуждае от GroupMember да има идентификатор за .destroy, за да работи по този начин.

Потърсете :id => false във вашата миграция и се отървете от него. след това повторете миграцията.

Надявам се това да помогне.

person jtesch    schedule 25.02.2011
comment
Това проработи, благодаря! Свикнал съм с PHP/MYSQL и използвам съставни първични ключове за много към много. - person Dan Martens; 11.03.2011

Мисля, че вашата таблица group_members в базата данни няма първичен ключ. Може би не сте го настроили. Така че, когато създадете нов обект GroupMember и го запазите, той няма да има идентификатор. Не можете да унищожите обект без id (първичен ключ).

person rubyprince    schedule 25.02.2011

Сблъсках се със същите проблеми, които описвате, и публикацията ви ме накара да потърся допълнително решение. Ето какво намерих:

1- Вземете тази съставна библиотека с първични ключове от http://compositekeys.rubyforge.org/ 2- Добавете я към вашият gem файл 3- Добавете следното към GroupMember set_primary_keys [:user_id, :group_id]

  • забележете set_primary_keys, а не set_primary_key

това ще върне точния основен, когато извикате GroupMember.primary_key, когато унищожението търси .primary_key, то сега ще го намери.

Опитайте в конзолата си: gm = GroupMember.first gm.destroy

Надявам се това да помогне =)

person Abdo    schedule 20.03.2011

Ако използвате асоциации и по някаква причина сте избрали да не използвате идентификатора по подразбиране на Active Records, можете да зададете идентификатора по подразбиране с помощта на "set_primary_key", така че методи като намиране и унищожаване да работят правилно.

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
person zarazan    schedule 25.06.2011

Опитахте ли m.reload.destroy вместо m.destroy, за да видите какво ще се случи?

person José Fernandes    schedule 25.02.2011