Как работает has_one: through? - PullRequest
       13

Как работает has_one: through?

5 голосов
/ 18 сентября 2008

У меня есть три модели:

class ReleaseItem < ActiveRecord::Base
  has_many :pack_release_items
  has_one :pack, :through => :pack_release_items
end

class Pack < ActiveRecord::Base
  has_many :pack_release_items
  has_many :release_items, :through=>:pack_release_items
end

class PackReleaseItem < ActiveRecord::Base
  belongs_to :pack
  belongs_to :release_item
end

Проблема в том, что во время выполнения, если я добавляю пакет в release_item, он не знает, что пакет является пакетом. Например:

Loading development environment (Rails 2.1.0)
>> item = ReleaseItem.new(:filename=>'MAESTRO.TXT')
=> #<ReleaseItem id: nil, filename: "MAESTRO.TXT", created_by: nil, title: nil, sauce_author: nil, sauce_group: nil, sauce_comment: nil, filedate: nil, filesize: nil, created_at: nil, updated_at: nil, content: nil>
>> pack = Pack.new(:filename=>'legion01.zip', :year=>1998)
=> #<Pack id: nil, filename: "legion01.zip", created_by: nil, filesize: nil, items: nil, year: 1998, month: nil, filedate: nil, created_at: nil, updated_at: nil>
>> item.pack = pack
=> #<Pack id: nil, filename: "legion01.zip", created_by: nil, filesize: nil, items: nil, year: 1998, month: nil, filedate: nil, created_at: nil, updated_at: nil>
>> item.pack.filename
NoMethodError: undefined method `filename' for #<Class:0x2196318>
    from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/base.rb:1667:in `method_missing_without_paginate'
    from /usr/local/lib/ruby/gems/1.8/gems/mislav-will_paginate-2.3.3/lib/will_paginate/finder.rb:164:in `method_missing'
    from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/associations/association_collection.rb:285:in `send'
    from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/associations/association_collection.rb:285:in `method_missing_without_paginate'
    from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/base.rb:1852:in `with_scope'
    from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/associations/association_proxy.rb:168:in `send'
    from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/associations/association_proxy.rb:168:in `with_scope'
    from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/associations/association_collection.rb:281:in `method_missing_without_paginate'
    from /usr/local/lib/ruby/gems/1.8/gems/mislav-will_paginate-2.3.3/lib/will_paginate/finder.rb:164:in `method_missing'
    from (irb):5
>> 

Кажется, у меня должен быть доступ к item.pack, но он не знает, что этот пакет является элементом Pack.

Ответы [ 3 ]

6 голосов
/ 18 сентября 2008

Похоже, что вы используете has_one: through правильно. Проблема, которую вы видите, связана с сохранением объектов. Чтобы ассоциация работала, объект, на который ссылаются, должен иметь идентификатор для заполнения поля model_id для объекта. В этом случае PackReleaseItems имеют поля pack_id и release_item_id, которые необходимо заполнить для правильной работы ассоциации. Попробуйте сохранить перед доступом к объектам через ассоциацию.

2 голосов
/ 18 сентября 2008

Ваша проблема в том, как вы связываете ReleaseItem и Pack.

has_many :through и has_one :through оба работают через объект, который также действует как таблица соединения, в данном случае PackReleaseItem. Так как это не просто таблица соединения (если это так, вы должны просто использовать has_many без :through), для правильного создания ассоциации необходимо создать объект соединения, например:

>> item.pack_release_items.create :pack => pack

То, что вы делаете со своим вызовом item.pack = pack, просто связывает объекты в памяти. Когда вы идете, чтобы посмотреть его снова, он выглядит "through" pack_release_items, который пуст.

1 голос
/ 18 сентября 2008

Вы хотите сохранить или создать (вместо нового) предмет и пакет. В противном случае базе данных не назначены идентификаторы для ассоциации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...