2008-09-18 13 views
5

Ich habe drei Modelle:Wie funktioniert has_one: durch Arbeit?

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 

Das Problem ist, dass während der Ausführung, wenn ich eine Packung zu einem release_item hinzufügen es nicht bewusst ist, dass die Packung eine Packung ist. Zum Beispiel:

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

Es scheint, dass ich Zugriff auf item.pack hätte, aber es ist nicht bewusst, dass das Paket ein Pack-Element ist.

Antwort

6

Es scheint, dass Ihre Verwendung von has_one: through korrekt ist. Das Problem, das Sie sehen, hat mit dem Speichern von Objekten zu tun. Damit eine Verknüpfung funktioniert, muss das Objekt, auf das verwiesen wird, über eine ID verfügen, um das Feld model_id für das Objekt zu füllen. In diesem Fall haben PackReleaseItems ein pack_id und ein release_item_id Feld, die ausgefüllt werden müssen, damit die Verbindung korrekt funktioniert. Versuchen Sie zu speichern, bevor Sie über eine Zuordnung auf Objekte zugreifen.

+0

Aber wenn ich has_many: through, gehört_to oder has_one, muss ich nicht zuerst speichern. – lordscarlet

+0

Ja, das scheint sich darum gekümmert zu haben. Ich glaube nicht, dass ich das mit anderen Verbänden machen muss. – lordscarlet

+0

Passt das auf? Können Sie einen Clip Ihrer interaktiven Konsolensitzung posten? Ich habe mit Rails 2.1.0 eine kleine Testapplikation gemacht und auch das vorherige Speichern hat der Situation nicht geholfen, weshalb ich meine Antwort eingereicht habe. –

2

Ihr Problem besteht darin, wie Sie die ReleaseItem und die Pack zuordnen.

has_many :through und has_one :through arbeiten beide durch ein Objekt, das auch als Join-Tabelle fungiert, in diesem Fall . Da diese Tabelle nicht nur ein Join ist (wenn es, sollten Sie nur has_many ohne :through verwenden), die Schaffung richtig der Verein das Objekt verbinden erfordert die Schaffung, etwa so:

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

Was Sie mit Ihrem item.pack = pack tun call verbindet einfach die Objekte im Speicher. Wenn Sie es erneut suchen, sieht es "through" die pack_release_items, die leer ist.

+0

>> item.pack_release_items.create: pack => pack => # >> item.pack => null – lordscarlet

+0

Das konnte geschehen, weil das Paket nicht alle Validatoren erfüllt hat. Ich werde es wieder versuchen, wenn ich nach Hause komme. – lordscarlet

+0

Pack ist in Ihrem Beispiel nichts, weil das Pack nicht gespeichert wurde - Sie können "pack_id: nil" in Ihrem PackReleaseItem sehen. –

1

Sie möchten den Artikel und das Paket speichern oder erstellen (statt neu). Andernfalls hat die Datenbank keine IDs für die Zuordnung zugewiesen.