2008-09-18 17 views
5

que tengo tres modelos:¿Cómo funciona has_one: a través del trabajo?

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 

El problema es que, durante la ejecución, si agrego un paquete a un release_item no es consciente de que el paquete es un paquete. Por ejemplo:

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

Parece que debería tener acceso a item.pack, pero no tengo conocimiento de que el paquete es un artículo de paquete.

Respuesta

6

Parece que el uso de has_one: through es correcto. El problema que estás viendo tiene que ver con guardar objetos. Para que una asociación funcione, el objeto al que se hace referencia debe tener una identificación para rellenar el campo model_id para el objeto. En este caso, PackReleaseItems tienen un campo pack_id y release_item_id que deben llenarse para que la asociación funcione correctamente. Intente guardar antes de acceder a los objetos a través de una asociación.

+0

Pero si uso has_many: through, belongs_to, o has_one, no tengo que guardar primero. – lordscarlet

+0

Sí, parece que se han encargado de eso. Sin embargo, no creo que tenga que hacer eso con otras asociaciones. – lordscarlet

+0

¿Eso se ocupa de eso? ¿Puedes publicar un clip de tu sesión de consola interactiva? Hice una pequeña aplicación de prueba con Rails 2.1.0 e incluso ahorrar de antemano no ayudó a la situación, por lo que presenté mi respuesta. –

2

Tu problema es cómo estás asociando el ReleaseItem y el Pack.

has_many :through y has_one :through funcionan a través de un objeto que también actúa como una tabla de combinación, en este caso PackReleaseItem. Dado que esto no es sólo una tabla de unión (si lo fuera, sólo debe utilizar has_many sin :through), adecuada de crear la asociación requiere crear el objeto se unen, así:

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

Lo que está haciendo con su item.pack = pack llamar es simplemente asociar los objetos en la memoria. Cuando vaya a buscarlo nuevamente, se ve "through" pack_release_items, que está vacío.

+0

>> item.pack_release_items.create: pack => paquete => # >> item.pack => nil – lordscarlet

+0

Eso pudo haber ocurrido porque el paquete no satisfacía todos los validadores. Lo intentaré de nuevo cuando llegue a casa. – lordscarlet

+0

El paquete es nulo en el ejemplo porque el paquete no se ha guardado; puede ver "pack_id: nil" en su PackReleaseItem. –

1

Desea guardar o crear (en lugar de nuevo) el artículo y el paquete. De lo contrario, la base de datos no ha asignado identificadores para la asociación.

Cuestiones relacionadas