2009-03-31 15 views
3

Sagen wir, ich habe Modelle: User und Item und Beziehung viele-zu-viele zwischen ihnen. So erhalten Sie Benutzer, die genau (nicht mehr) Elemente mit den definierten Attributen haben, d. H. Benutzer mit Elementen mit Farben = ['rot', 'schwarz'].Umgekehrt has_many in Rails

Natürlich kann ich so etwas tun:

User.all :joins => [:items, :items], :conditions => {:"items.color" => "red", :"items_users.color" => 'black'} 

Aber für mehr Attribute, es wird ziemlich umständlich. Ich kann auch tun:

User.all(:conditions => ["items.color in (?), ['red', 'black']], :include => :items) 

Aber dies gibt auch Benutzer mit Artikeln Farben = [ ‚rot‘, ‚schwarz‘, ‚blau‘, ‚etc‘]

So ist die einzige Lösung, die ist alles zu bekommen und mit Ruby-Syntax zu sortieren? Wie macht man es in einer SQL-Abfrage oder Rails AR-Syntax?

Antwort

1

Die Art und Weise, die Programmierer Zeit und Lesbarkeit, meiner Meinung nach optimiert:

#get all users who have items which are both red and black but no other colors 
candidate_users = User.all(:include => :items) 
candidate_users.reject! do |candidate| 
    candidate.items.map {|item| item.color}.sort != ['black', 'red'] 
end 

Wenn Sie erwarten, durch eine Metrik LKW-Ladung von Benutzern dort zu Looping, dann müssen Sie es auf SQL-up. Warnung: SQL ist nicht meine Tasche, Baby: Test vor dem Gebrauch.

select users.*, items.* FROM users 
    INNER JOIN items_users ON (items_users.user_id = users.id) 
    INNER JOIN items ON (items_users.item_id = items.id) 
    GROUP BY users.id HAVING COUNT(DISTINCT items.color) = 2 

Was ich denke, dass das Böse Chaos tut:

1) Grabs jeden Benutzer/item Kombination 2) worfelt an Benutzer nach unten, die Elemente von genau 2 verschiedene Farben haben

Das bedeutet, Sie‘ ll müssen:

candidate_users.reject! do |candidate| 
    candidate.items.map {|item| item.color}.sort != ['black', 'red'] 
end 

Sie wahrscheinlich die Notwendigkeit der Rubin hier völlig beseitigen können, aber die SQL wird sieben Aromen von hässlich zu bekommen. (Kreuz verbindet, oh mein ...)

+0

Obwohl einfach, bricht dies Schienen Konventionen, und verhindert Lazy-Laden in Ketten (vorausgesetzt, dies würde in eine "Lambda" gehen –

Verwandte Themen