2016-04-25 9 views
1

Ich versuche, einen Bereich in Rails hinzufügen, die nur einträgt, wenn Argumente in es übergeben werden - gibt es eine nette Möglichkeit, das unordentliche 1=1 Standardargument zu vermeiden?Ruby Scope/ActiveRecord Query no-ops

scope :tagged, -> (tags) { [tags].flatten.compact.empty? ? where('1 = 1') : where("#{self.table_name}.tags @> ARRAY[?]::varchar[]", [tags].flatten.compact)} 

Im Grunde, was ist das Äquivalent von where('1=1') in einem Umfang, der die aktuelle Abfrage zurückkehren und fortVerkettungs erlauben? Returning self funktioniert nicht - es gibt das Objekt zurück und alle Ketten müssen von Grund auf neu aufgebaut werden.

Antwort

3

Der Bereich all löst Ihr Problem. Aufspaltung Ihre großen on-Liner in etwas mehr lesbar gibt:

scope :tagged, -> (tags) do 
    if [tags].flatten.compact.empty? 
    all 
    else 
    where(
     "#{self.table_name}.tags @> ARRAY[?]::varchar[]", 
     [tags].flatten.compact 
    ) 
    end 
end 

Dies kann jedoch weiterhin einen Schritt genommen werden: Wenn ein Schienen Umfang nil zurückgibt, dann wird es implizit Anruf all sowieso! Mit anderen Worten, wir können einfach schreiben:

scope :tagged, -> (tags) do 
    if [tags].flatten.compact.present? 
    where(
     "#{self.table_name}.tags @> ARRAY[?]::varchar[]", 
     [tags].flatten.compact 
    ) 
    end 
end 
+0

Ich würde auch empfehlen, wenn möglich, eine Vereinfachung der Code, der diesen Bereich nennt: Ihr Aufruf '.flatten.compact' ein bisschen vertrackt ist! Im Idealfall sollten Sie mehr Vertrauen in die Datenstrukturen haben, die zwischen Methoden übergeben werden. –

+0

'[Tags] .flatten.compact' ist eigentlich sehr nützlich - man kann den Scope mit' nil', einem einzelnen 'tag' und einem Array von' [tags] 'verwenden. Mehr über Flexibilität als über Misstrauen. –

+0

[* Tags] ist meine bevorzugte Art, das zu erreichen. Genau das, was du sagst (erlaubt auch '[]' zusätzlich zu 'nil') und nicht mehr. –