2010-11-14 6 views
0

Баунти в размере 25 долларов США за первое рабочее решение.Strange has_many: через выпуск с добавлением объектов в коллекцию

Я вижу действительно странное 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 

Добавление объекта к: путем сбора, как представляется, добавить два элемента в корневой ассоциации, как отсутствует идентификатор объект добавлен.

Есть ли у кого-нибудь идеи, почему это может произойти?

Edit: Даже это не работает:

>> 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>] 
+0

Не решение, но вы должны добавить 'create_table: call_list_memberships,: id => false do | t |' – Zabba

+0

Просто отметим, что я исключил имя класса Number (попробованное PhoneNumber) и политический университет STI в качестве вклада в Эта проблема. –

+0

Zabba, вы совершенно правы, но удаление идентификатора из CallListMemberships теперь приводит к созданию трех создаваемых записей, что делает его еще менее значимым. –

ответ

2

Ok, так что после долгого и довольно расстраивает поисках ответа на это, я, наконец, отслеживаются и это чертовски неловко.

Я использовал следующий динамический 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

Черт, это неловко! Я просто потратил 15 минут, пытаясь понять это сам. Благодарю. – JohnMetta

0

Это действительно странное поведение. Я не уверен, связано ли это только с 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 
+0

К сожалению, записи не сохраняются в базе данных правильно. Выполнение p1.call_list_memberships.first.number возвращает nil –

+0

Rails/Ruby версии? – zetetic

+0

btw Я пробовал это на Ruby 1.8.7/Rails 2.3.8, и поведение отличается. На Ruby 1.9.2/Rails 3.0.1 я вижу дублируемое 'CallListMembership', но вызов' p1.reload' исправляет кажущееся дублирование, и у DB есть все правильные строки. – zetetic

Смежные вопросы