Wenn ich einen Gültigkeitsbereich mit einem Lambda habe und abhängig vom Wert des Arguments ein Argument benötigt, weiß ich möglicherweise, dass es keine Übereinstimmungen gibt, möchte aber dennoch eine Beziehung zurückgeben, kein leeres Array:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
Was ich wirklich will, ist eine "none" -Methode, das Gegenteil von "all", die eine Beziehung zurückgibt, die noch verkettet werden kann, aber dazu führt, dass die Abfrage kurzgeschlossen wird.
ruby-on-rails
activerecord
relation
dzajic
quelle
quelle
Antworten:
In Rails 4 gibt es jetzt einen "richtigen" Mechanismus:
quelle
Model.scoped
macht, was Sie in Schienen 3 suchen.Model.none
funktioniert nicht. Sie müssen einen Ihrer echten Modellnamen verwenden, z. B.User.none
oder was-haben-Sie.Eine portablere Lösung, die keine "ID" -Spalte benötigt und nicht davon ausgeht, dass es keine Zeile mit der ID 0 gibt:
Ich bin immer noch auf der Suche nach einem "richtigen" Weg.
quelle
scope :none, -> { where("false") }
Kommen in Schienen 4
In Rails 4 wird eine Verkettung
ActiveRecord::NullRelation
von Anrufen wie zurückgegebenPost.none
.Weder es noch verkettete Methoden erzeugen Abfragen an die Datenbank.
Nach den Kommentaren:
Siehe den Quellcode .
quelle
Sie können einen Bereich mit dem Namen "none" hinzufügen:
Dadurch erhalten Sie eine leere ActiveRecord :: Relation
Sie können es auch in einem Initialisierer zu ActiveRecord :: Base hinzufügen (wenn Sie möchten):
Viele Möglichkeiten, um so etwas zu bekommen, aber sicherlich nicht das Beste, um in einer Codebasis zu bleiben. Ich habe den Bereich verwendet: keine, wenn ich umgestalte und feststelle, dass ich für kurze Zeit eine leere ActiveRecord :: Relation garantieren muss.
quelle
where('1=2')
könnte etwas prägnanter seinModel.none
Sie wie folgt vor.Ist eine gefährliche Lösung, da Ihr Zielfernrohr möglicherweise verkettet ist.
User.none.first
gibt den ersten Benutzer zurück. Es ist sicherer zu bedienen
quelle
Ich denke, ich bevorzuge die Art und Weise, wie dies aussieht, gegenüber den anderen Optionen:
Zu so etwas führen:
quelle
where(false)
ich den Job nicht machen sollte - er lässt den Umfang unverändert.limit(0)
dies überschrieben wird, wenn Sie.first
oder.last
später in der Kette anrufen , da RailsLIMIT 1
an diese Abfrage angehängt wird .none
unten erwähnte Beziehung.Verwenden Sie Scoped:
Sie können Ihren Code aber auch vereinfachen mit:
Wenn Sie ein leeres Ergebnis wünschen, verwenden Sie dies (entfernen Sie die if-Bedingung):
quelle
Es ist möglich und das ist:
http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none
Korrigiere mich, wenn ich falsch liege.
quelle
Es gibt auch Varianten, aber alle fordern db an
quelle
where(false)
oderwhere(nil)
wird einfach ignoriert.