Странный has_many: из-за проблемы с добавлением объектов в коллекцию - PullRequest
0 голосов
/ 14 ноября 2010

Щедрость 25 долларов за первый рабочий раствор.

Я вижу действительно странное has_many: из-за проблемы с ActiveRecord.

С этими классами:

create_table :numbers do |t|
  t.string :phone_number
end
create_table :call_lists do |t|
  t.string :type
  t.string :name
  t.integer :user_id
  t.integer :county_id
  t.integer :state_id
end
create_table :call_list_memberships do |t|
  t.integer :call_list_id
  t.integer :number_id
end

class CallList < ActiveRecord::Base
  attr_accessible :name
  has_many :call_list_memberships, :autosave => true
  has_many :numbers, :through => :call_list_memberships, :autosave => true
  belongs_to :user
end

class PoliticalDistrict < CallList
end

class CallListMembership < ActiveRecord::Base
  belongs_to :call_list
  belongs_to :number
end

class Number < ActiveRecord::Base
  attr_accessible :phone_number
  has_many :call_list_memberships
  has_many :call_lists, :through => :call_list_memberships
end

У меня такое поведение:

>> p1 = PoliticalDistrict.first
=> #<PoliticalDistrict id: 2, type: "PoliticalDistrict", name: "Random political district", user_id: nil, county_id: nil, state_id: nil>
>> p1.numbers
=> []
>> p1.call_list_memberships
=> []
>> n1 = Number.first
=> #<Number id: 1, phone_number: "07921088939">
>> p1.numbers << n1
=> [#<Number id: 1, phone_number: "07921088939">]
>> p1.numbers
=> [#<Number id: 1, phone_number: "07921088939">]
>> p1.call_list_memberships
=> [#<CallListMembership id: 6, call_list_id: 2, number_id: nil>, #<CallListMembership id: 6, call_list_id: 2, number_id: nil>]
>> p1.save
=> true

Добавление объекта в коллекцию: through добавляет два элемента в корневую ассоциацию, в обоих из которых отсутствует идентификатор добавленного объекта.

У кого-нибудь есть идеи, почему это может происходить?

Редактировать: Даже это не работает:

>> pd2.call_list_memberships.create :number => Number.first
=> #<CallListMembership call_list_id: 2, number_id: nil>
>> Number.first
=> #<Number id: 1, phone_number: "07921088939">
>> pd2.call_list_memberships
=> [#<CallListMembership call_list_id: 2, number_id: nil>]

Ответы [ 2 ]

2 голосов
/ 15 ноября 2010

Хорошо, так что после долгого и довольно разочаровывающего поиска ответа на этот вопрос я, наконец, разыскал проблему, и это чертовски неловко.

Я использовал следующий динамический код attr_accesssible в инициализаторе:

class ActiveRecord::Base
  attr_accessible
  attr_accessor :accessible

  private

  def mass_assignment_authorizer
    if accessible == :all
      self.class.protected_attributes
    else
      super + (accessible || [])
    end
  end
end

О котором я удобно забыл и из-за которого number_id стал недоступен (благодаря пустому вызову attr_accessible).

0 голосов
/ 14 ноября 2010

Это действительно странное поведение. Я не уверен, относится ли это только к IRB или к ActiveRecord. Вы заметите, что ассоциация правильно сохраняется в базе данных, но результаты вызовов IRB на счетчиках ассоциации неверны. Используя ваш пример:

>> p1.call_list_memberships
=> [#<CallListMembership id: 6, call_list_id: 2, number_id: nil>, #<CallListMembership id: 6, call_list_id: 2, number_id: nil>]
>> p1.save
>> p1.call_list_memberships.length
=> 2 # Huh?
>> p1.call_list_memberships.size
=> 2 # Wtf?
>> p1.call_list_memberships.count
=> 1 # That's more like it
>> p1.reload # refresh the data
>> p1.call_list_memberships.length
=> 1 # now the associations are correct
>> p1.call_list_memberships.size
=> 1

Что еще более странно, он повторяет строку таблицы соединений в ассоциации - проверьте идентификаторы объектов двух CallListMemberships, и вы увидите, что они одинаковы.

EDIT

Создание ассоциации с использованием таблицы соединений, по-видимому, позволяет избежать этой проблемы:

>> p1=PoliticalDistrict.create(:name=>"Sample")
=> #<PoliticalDistrict id: 1, type: "PoliticalDistrict", name: "Sample", user_id: nil, county_id: nil, state_id: nil, created_at: "2010-11-14 21:33:09", updated_at: "2010-11-14 21:33:09"> 
>> n1=Number.create(:phone_number=>"123")
=> #<Number id: 1, phone_number: "123", created_at: "2010-11-14 21:33:22", updated_at: "2010-11-14 21:33:22"> 
>> p1.call_list_memberships.create(:number=>n1)
=> #<CallListMembership id: 1, call_list_id: 1, number_id: 1, created_at: "2010-11-14 21:33:39", updated_at: "2010-11-14 21:33:39"> 
>> p1.call_list_memberships
=> [#<CallListMembership id: 1, call_list_id: 1, number_id: 1, created_at: "2010-11-14 21:33:39", updated_at: "2010-11-14 21:33:39">] 
>> p1.call_list_memberships.length
=> 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...