Comment has_one: à travers le travail?
-
01-07-2019 - |
Question
J'ai trois modèles:
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
Le problème est que, lors de l'exécution, si j'ajoute un pack à un release_item, il n'est pas conscient que ce pack est un pack. Par exemple:
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
>>
Il semble que je devrais avoir accès à item.pack, mais il n’est pas conscient du fait que le pack est un élément du pack.
La solution
Il semble que votre utilisation de has_one: through est correcte. Le problème que vous voyez concerne la sauvegarde des objets. Pour qu'une association fonctionne, l'objet qui est référencé doit avoir un identifiant pour renseigner le champ model_id
de l'objet. Dans ce cas, PackReleaseItems
possède un id_package
et un champ release_item_id
qui doivent être renseignés pour que l'association fonctionne correctement. Essayez d’enregistrer avant d’avoir accès aux objets via une association.
Autres conseils
Votre problème réside dans la manière dont vous associez le ReleaseItem
et le Pack
.
has_many: through
et has_one: through
fonctionnent tous les deux via un objet servant également de table de jointure, dans ce cas-ci PackReleaseItem
. Comme il ne s'agit pas simplement d'une table de jointure (si c'était le cas, vous devriez simplement utiliser has_many
sans : via
), pour créer correctement l'association, vous devez créer l'objet de jointure, comme suit:
>> item.pack_release_items.create :pack => pack
Ce que vous faites avec votre appel item.pack = pack
consiste simplement à associer les objets en mémoire. Lorsque vous le consultez à nouveau, il affiche " à
" pack_release_items
, qui est vide.
Vous souhaitez enregistrer ou créer (au lieu de nouveau) l'élément et le pack. Sinon, la base de données n'a pas attribué d'identifiant pour l'association.