default_scope in Fortsetzung
-
12-12-2019 - |
Frage
In ActiveRecord gibt es eine default_scope
klassenmethode zum Angeben eines Standardbereichs.Beispielsweise
class User < ActiveRecord::Base
default_scope where(:deleted => false)
end
User.all # => SELECT * FROM users WHERE deleted = 0;
Wie kann ich das machen in Sequel::Model
?
BEARBEITEN:
Nach einigem Googeln fand ich schließlich einige nützliche Informationen.
class User < Sequel::Model
# Define some "scopes" (filters on the dataset)
dataset_module do
def existing
filter(deleted: false)
end
def active
filter(disabled: false)
end
end
# This is the equivalent to a default_scope. Set one of the datasets
# as the default dataset for this model.
set_dataset(self.active)
end
Die generierte Abfrage sieht dann so aus:
User.all # => SELECT * FROM `users` WHERE (`deleted` IS FALSE)
Übrigens:Das Äquivalent zu unscoped
is unfiltered
:
User.unfiltered.all # => SELECT * FROM `users`
Aber, gibt es ein Problem.Wenn Sie versuchen, einen Benutzer zu aktualisieren, den Sie aus einem ungefilterten Datensatz erhalten haben, wird versucht, den Benutzer mithilfe des angegebenen Datensatzes zu aktualisieren.
User.create(disabled: true, deleted: true)
User.all # => []
u = User.unfiltered.first # => Given user
u.disabled = false
u.save # => UPDATE users SET ... WHERE (disabled IS FALSE AND id = 1)
# => Sequel::NoExistingObject: Attempt to update object did not result in a single row modification
Also bin ich wieder am Anfang. Irgendeine Problemumgehung dafür?
Lösung
Die beste Problemumgehung besteht darin, das Problem zu vermeiden, indem kein Standardbereich vorhanden ist.In den meisten Fällen ist ein Standardbereich eine schlechte Idee.Wenn Sie möchten, dass die meisten Ihrer Abfragen einen Bereich verwenden, wenden Sie den Bereich in diesen Abfragen manuell an, verwenden Sie keinen Standardbereich und versuchen Sie, den Bereich in anderen Abfragen zurückzusetzen.Ein Standardbereich ist nur sinnvoll, wenn aller von Ihren Abfragen wird dieser Bereich verwendet.
Sie können dies auch durch Unterklassen behandeln (Benutzer hat keinen Gültigkeitsbereich, aktiver Benutzer < Benutzer ist Gültigkeitsbereich).Ich finde jedoch, dass der explizite Scoping-Ansatz besser funktioniert.
Wenn Sie jedoch wirklich einen Standardbereich verwenden möchten, kann das Problem der Aktualisierung einer Modellinstanz außerhalb des Standardbereichs des Modells wie folgt umgangen werden:
User.instance_dataset.unfiltered!