2009-01-09 14 views
5

Ich frage mich, was die einfachste/eleganteste Art der Auswahl von Attributen aus Join-Modellen in has_many: durch Assoziationen ist.Elegant Auswahl von Attributen aus has_many: durch Join-Modelle in Rails

Können sagen, wir haben Angebote, Kataloge und CatalogItems mit der folgenden Item-Klasse:

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

Zusätzlich können sagen, dass CatalogueItems eine Position Attribut hat und dass es nur eine CatalogueItem zwischen jedem Katalog und jedes Element .

Die naheliegendste, aber etwas frustrierend Art und Weise die Position Attribut abzurufen ist:

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

Das ist ärgerlich, weil es, dass wir scheint in der Lage sein sollte @ item.catalogs.first.position zu tun, da wir komplett haben spezifiziert, welche Position wir haben wollen: diejenige, die dem ersten von @ items Katalogen entspricht.

Der einzige Weg, die ich gefunden habe, dieses zu erhalten ist:

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

Jetzt habe ich Item.catalogs.first.position tun kann. Dies scheint jedoch ein bisschen wie ein Hack zu sein - ich füge ein zusätzliches Attribut zu einer Catalog-Instanz hinzu. Es eröffnet auch die Möglichkeit, eine Ansicht in zwei verschiedenen Situationen zu verwenden, in denen ich @ Catalogs mit einer Catalog.find oder mit einem @ item.catalogs bevölkert. In einem Fall wird die Position vorhanden sein und in der anderen nicht.

Hat jemand eine gute Lösung dafür?

Danke.

Antwort

0

Sie können etwas tun:

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

Oder man kann es in in einer Instanzmethode des Item-Modell wickeln:

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

und dann rufen Sie einfach es wie folgt aus:

@item.position_in_first_catalogue 
+1

Die Instanz-Methode funktioniert, aber es scheint immer noch so, als sollte es einen besseren Weg geben. Ich wollte den ersten Katalog nicht speziell, ich habe ihn nur als Beispiel benutzt. Ich denke du könntest @ item.position_in_catalog (catalog_id) machen. – arjun

+0

Ja, es ist wirklich einfach, es für @ otem.position_in_catalog (Katalog) umzuschreiben. Ich sehe jedoch keinen anderen Weg, wie Sie das umsetzen können, was Sie wollen. –

+0

@ item.catalogs.first.position <- dies gibt keine Position an. Mit @ item.catalogs geben Sie nur eine Teilmenge aller Kataloge an, aus der Sie dann die erste auswählen.Also, was Sie am Ende haben, ist nur ein Katalog, der agnostisch über die Art und Weise, wie Sie es erhalten haben, ist. –

-1

Sie sollten @ catalog.catalog_item.position ausführen können, wenn Sie das andere Ende der Verknüpfung angeben.

class Catalog < ActiveRecord::Base 
    belongs_to :catalog_item 
end 

Jetzt können Sie Catalog.first.catalog_item.position tun.

+0

Ein Katalog has_many catalog_items und has_many items durch catalog_items, also das ist nicht ganz das, was ich suchte..dank aber. – arjun

+0

Dies funktioniert nicht für die Viele-zu-Viele-Beziehung, die durch has_many: through ausgedrückt wird. –

-2

Warum Sie nicht nur

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

warum gehst du durch Kataloge? Es macht für mich keinen Sinn, da Sie nach dem ersten ANY-Katalog suchen !?

+0

Ich bin mir nicht sicher, was Sie mit "ersten ANY Katalog" meinen. Wie auch immer, ich suche nicht unbedingt nach dem ersten Katalog - das war nur ein Beispiel. Sagen Sie, dass ein Artikel hat 50 Kataloge und ich möchte die Position des Artikels in Katalog # 6823 .. – arjun

+0

ich meine, scheint wie Sie brauchen nur erste Position von catalog_items für aktuelle Artikel und Kataloge sind unnötig für diese Abfrage. – aivarsak

+0

Sie wissen nicht, welche Position Sie von catalog_items haben möchten. Wenn ein Artikel zu 50 Katalogen gehört und Sie möchten, dass er im 47. Katalog steht (wissen Sie aber nicht, in welcher Reihenfolge die Kataloge liegen), benötigen Sie den Katalog. – arjun