Jeśli mam model ActiveRecord :: Base z domyślnym zakresem:
class Foo < ActiveRecord::Base
default_scope :conditions => ["bar = ?",bar]
end
Czy można to zrobić Foo.find
bez korzystania z default_scope
warunków? Innymi słowy, czy możesz przesłonić domyślny zakres?
Myślałem, że za pomocą „default” w nazwie sugeruje, że był przeciążać, inaczej go nazwać coś takiego global_scope
, prawda?
ruby-on-rails
Gareth
źródło
źródło
Odpowiedzi:
Krótka odpowiedź: nie używaj,
default_scope
chyba że naprawdę musisz. Prawdopodobnie lepiej będzie, jeśli skorzystasz z nazwanych zakresów. Mając towith_exclusive_scope
na uwadze , możesz użyć, aby zastąpić domyślny zakres, jeśli zajdzie taka potrzeba.Spójrz na to pytanie, aby uzyskać więcej informacji.
źródło
default_scope
może wydawać się dobrym pomysłem, ale prawdopodobnie spowoduje wiele bólów głowy w okresie użytkowania aplikacji.with_exclusive_scope
został usunięty w szynach 3default_scope
to doskonałe narzędzie i są sytuacje, w których możesz inaczej, aledefault_scope
jest to po prostu słuszne. Na przykład, jeśli maszProduct
model, który mainactive
flagę, ustawienie adefault_scope { where inactive: false }
jest najlepszą rzeczą do zrobienia, ponieważ w 99% przypadków nie będziesz chciał wyświetlać nieaktywnego produktu. Następnie wystarczy zadzwonićunscoped
do pozostałych 1% przypadków, co prawdopodobnie jest panelem administracyjnym.W Rails 3:
źródło
def self.random; unscoped.order('rand()'); end
umieścisz to w metodzie klasowej, takiej jak: unscoped usuwa WSZYSTKIE sql przed nim, a nie tylko to, co jest wymienione w default_scope. Chociaż technicznie poprawna odpowiedź, uważaj, używającunstopped
unscoped
wtedy, gdy może bezpośrednio podążać za modelem, np.Foo.unscoped.blah()
Jest w porządku, ale nigdyFoo.blah().unscoped
.Jeśli wystarczy zmienić kolejność zdefiniowaną w
default_scope
, możesz skorzystać zreorder
metody .uruchamia następujący SQL:
źródło
scope :without_default_order, -> { reorder("") }
i możesz robić takie rzeczy, jakFoo.without_default_order.order("created_at ASC")
W niektórych sytuacjach lepiej czyta (może nie ta dokładna sytuacja, ale miałem taką).Ponieważ
4.1
możesz użyćActiveRecord::QueryMethods#unscope
do walki z domyślnym zakresem:Jest to obecnie możliwe do
unscope
rzeczy, takich jak::where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having
.Ale nadal unikaj używania of,
default_scope
jeśli możesz . To dla twojego dobra.źródło
Możesz przesłonić domyślny zakres przy użyciu
with_exclusive_scope
metody. Więc:with_exclusive_scope
dokumentacjaźródło
Rails 3 default_scope nie wydaje się być nadpisywany, tak jak w Rails 2.
na przykład
W mojej aplikacji używającej PostgreSQL, kolejność w domyślnym zakresie WINS. Usuwam wszystkie moje default_scope i koduję je jawnie wszędzie.
Pitfall Rails3!
źródło
Bar.foos.reorder(:created_at => :asc)
Z Rails 3+ możesz używać kombinacji bez zakresu i scalania:
źródło
User.unscoped.where(email: "[email protected]")
Na Railsach 5.1+ (a może wcześniej, ale testowałem to na 5.1) możliwe jest wyłączenie określonej kolumny, co jest idealnym rozwiązaniem do usuwania a
default_scope
w sposób, który może być użyty wewnątrz nazwanego zakresu. W przypadku programów operacyjnychdefault_scope
,Lub
Oba spowodują zapytanie sql, które nie stosuje oryginalnego zakresu, ale stosuje wszelkie inne warunki, które zostaną scalone w arel.
źródło
Cóż, zawsze możesz użyć starej listy ulubionych
find_by_sql
z pełnym zapytaniem. Na przykład: Model.find_by_sql ("SELECT * FROM models WHERE id = 123")źródło