Question

I have three models:

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

The problem is that, during execution, if I add a pack to a release_item it is not aware that the pack is a pack. For instance:

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

It seems that I should have access to item.pack, but it is unaware that the pack is a Pack item.

Was it helpful?

Solution

It appears that your usage of has_one :through is correct. The problem you're seeing has to do with saving objects. For an association to work, the object that is being referenced needs to have an id to populate the model_id field for the object. In this case, PackReleaseItems have a pack_id and a release_item_id field that need to be filled for the association to work correctly. Try saving before accessing objects through an association.

OTHER TIPS

Your problem is in how you're associating the ReleaseItem and the Pack.

has_many :through and has_one :through both work through an object that also acts as a join table, in this case PackReleaseItem. Since this is not just a join table (if it were, you should just use has_many without :through), properly creating the association requires creating the join object, like so:

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

What you're doing with your item.pack = pack call is simply associating the objects in memory. When you go to look it up again, it looks "through" the pack_release_items, which is empty.

You want to save or create (instead of new) the item and pack. Otherwise, the database has not assigned id's for the association.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top