5

Je me demande quelle est la manière la plus simple/la plus élégante de sélectionner des attributs à partir de modèles de jointure dans has_many: through associations.Sélection élégante des attributs de has_many: via les modèles de jointure dans Rails

Disons que nous avons des articles, des catalogues et CatalogItems avec les éléments suivants classe d'objet:

class Item < ActiveRecord::Base 
     has_many :catalog_items 
     has_many :catalogs, :through => :catalog_items 
end  

De plus, permet de dire que CatalogueItems a un attribut de position et qu'il n'y a qu'un seul CatalogueItem entre un catalogue et un article .

La façon la plus évidente, mais un peu frustrant pour récupérer l'attribut de position est la suivante:

@item   = Item.find(4) 
@catalog  = @item.catalogs.first 
@cat_item  = @item.catalog_items.first(:conditions => {:catalog_id => @catalog.id}) 
position  = @cat_item.position 

Ceci est gênant car il semble que nous devrions être en mesure de le faire @ item.catalogs.first.position puisque nous avons complètement spécifié quelle position nous voulons: celle qui correspond au premier des catalogues de @ item.

La seule façon que j'ai trouvé pour y arriver est:

class Item < ActiveRecord::Base 
     has_many :catalog_items 
     has_many :catalogs, :through => :catalog_items, :select => "catalogue_items.position, catalogs.*" 
end 

Maintenant, je peux faire Item.catalogs.first.position. Cependant, cela semble un peu un hack - j'ajoute un attribut supplémentaire sur une instance de catalogue. Cela ouvre également la possibilité d'essayer d'utiliser une vue dans deux situations différentes où je remplis @catalogs avec un fichier Catalog.find ou avec un fichier @ item.catalogs. Dans un cas, la position sera là, et dans l'autre, ce ne sera pas le cas.

Est-ce que quelqu'un a une bonne solution à cela?

Merci.

Répondre

0

Vous pouvez faire quelque chose comme ceci:

# which is basically same as your "frustrating way" of doing it 
@item.catalog_items.find_by_catalogue_id(@item.catalogs.first.id).position 

Ou vous pouvez envelopper dans dans une méthode d'instance du modèle de l'article:

def position_in_first_catalogue 
    self.catalog_items.find_by_catalogue_id(self.catalogs.first.id).position 
end 

puis simplement l'appeler comme ceci:

@item.position_in_first_catalogue 
+1

La méthode d'instance fonctionne, mais il semble tout de même qu'il devrait y avoir une meilleure solution. Je ne voulais pas spécifiquement le premier catalogue, je l'utilisais juste comme exemple. Je suppose que vous pouvez faire @ item.position_in_catalog (catalog_id). – arjun

+0

Oui, c'est vraiment facile de le réécrire pour @ otem.position_in_catalog (catalogue). Cependant, je ne vois pas d'autre moyen de mettre en œuvre ce que vous voulez. –

+0

@ item.catalogs.first.position <- ceci ne spécifie aucune position. Avec @ item.catalogs, il vous suffit de spécifier un sous-ensemble de tous les catalogues, à partir duquel vous sélectionnez le premier.Donc, ce que vous finissez avec est juste un catalogue, qui est agnostique sur la façon dont vous l'avez obtenu. –

-1

Vous devriez être en mesure de faire @ catalog.catalog_item.position si vous fournissez l'autre extrémité de l'association.

class Catalog < ActiveRecord::Base 
    belongs_to :catalog_item 
end 

Maintenant, vous pouvez faire Catalog.first.catalog_item.position.

+0

Un catalogue has_many catalog_items et has_many articles par catalogue_items, donc ce n'est pas tout à fait ce que je cherchais .. merci cependant. – arjun

+0

Cela ne fonctionnera pas pour la relation many-to-many exprimée par has_many: through. –

-2

Pourquoi ne pas simplement

@item = Item.find(4) 
position = @item.catalog_items.first.position 

pourquoi allez-vous à travers les catalogues? Cela n'a aucun sens pour moi puisque vous cherchez d'abord n'importe quel catalogue !?

+0

Je ne suis pas sûr de ce que vous entendez par "premier catalogue de tout." De toute façon, je ne cherche pas forcément le premier catalogue - ce n'était qu'un exemple. Dire qu'un article a 50 catalogues et je veux la position de l'article dans le catalogue # 6823 .. – arjun

+0

Je veux dire, semble que Vous devez juste la première position de catalog_items pour l'article en cours et les catalogues sont inutiles pour cette requête. – aivarsak

+0

Vous ne savez pas QUELLE position vous voulez à partir de catalog_items. Si un article appartient à 50 catalogues et que vous voulez qu'il soit positionné dans le 47ème catalogue (mais vous ne savez pas dans quel ordre se trouvent les catalogues), vous avez besoin du catalogue. – arjun

Questions connexes