Si j'ai un modèle ActiveRecord :: Base avec une portée par défaut:
class Foo < ActiveRecord::Base
default_scope :conditions => ["bar = ?",bar]
end
Existe-t-il un moyen de faire un Foo.find
sans utiliser les default_scope
conditions? En d'autres termes, pouvez-vous remplacer une étendue par défaut?
J'aurais pensé que l'utilisation de «default» dans le nom suggérerait qu'il était remplaçable, sinon cela s'appellerait quelque chose comme global_scope
, non?
ruby-on-rails
Gareth
la source
la source
Réponses:
Réponse courte: ne pas utiliser
default_scope
sauf si c'est vraiment nécessaire. Vous serez probablement mieux avec des portées nommées. Cela dit, vous pouvez utiliserwith_exclusive_scope
pour remplacer la portée par défaut si vous en avez besoin.Jetez un œil à cette question pour plus de détails.
la source
default_scope
peut sembler une bonne idée, mais causera probablement plusieurs maux de tête pendant la durée de vie de votre application.with_exclusive_scope
a été retiré dans les rails 3default_scope
est un excellent outil et il y a des situations où vous pourriez faire autrement mais c'estdefault_scope
juste la bonne chose à faire. Par exemple, lorsque vous avez unProduct
modèle avec uninactive
indicateur, définir adefault_scope { where inactive: false }
est la meilleure chose à faire, puisque 99% ou des cas, vous ne voudrez pas afficher un produit inactif. Ensuite, vous appelez simplementunscoped
les 1% restants, ce qui est probablement un panneau d'administration.Dans Rails 3:
la source
def self.random; unscoped.order('rand()'); end
unscoped supprime TOUT SQL avant lui, pas seulement ce qui est répertorié sous default_scope. Bien que techniquement une réponse correcte, soyez prudent en utilisantunstopped
unscoped
quand il peut suivre directement un modèle, par exempleFoo.unscoped.blah()
c'est ok mais jamaisFoo.blah().unscoped
.Si tout ce dont vous avez besoin est de modifier l'ordre défini dans
default_scope
, vous pouvez utiliser lareorder
méthode .exécute le SQL suivant:
la source
scope :without_default_order, -> { reorder("") }
et vous pouvez faire des choses commeFoo.without_default_order.order("created_at ASC")
Dans certaines situations, elle se lit mieux (peut-être pas cette situation exacte, mais j'en avais une).Puisque
4.1
vous pouvez utiliserActiveRecord::QueryMethods#unscope
pour combattre la portée par défaut:Il est actuellement possible de
unscope
choses comme::where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having
.Mais évitez
default_scope
toujours d' utiliser ou si vous le pouvez . C'est pour ton bien.la source
Vous pouvez remplacer une étendue par défaut à l'aide de la
with_exclusive_scope
méthode. Alors:with_exclusive_scope
Documentationla source
Rails 3 default_scope ne semble pas être remplacé comme il l'a fait dans Rails 2.
par exemple
Dans mon application, en utilisant PostgreSQL, le classement dans la portée par défaut WINS. Je supprime tous mes default_scopes et je le code explicitement partout.
Pitfall Rails3!
la source
Bar.foos.reorder(:created_at => :asc)
Avec Rails 3+, vous pouvez utiliser une combinaison de non-cadré et de fusion:
la source
User.unscoped.where(email: "[email protected]")
Sur Rails 5.1+ (et peut-être plus tôt, mais j'ai testé cela fonctionne sur 5.1), il est possible de délimiter une colonne spécifique, ce qui à mon humble avis est la solution idéale pour supprimer un
default_scope
d'une manière qui peut être utilisée dans une portée nommée. Dans le cas des POdefault_scope
,Ou
Les deux aboutiront à une requête SQL qui n'applique pas la portée d'origine, mais qui applique toutes les autres conditions fusionnées dans l'arel.
la source
Eh bien, vous pouvez toujours utiliser l'ancien favori
find_by_sql
avec la requête complète. Par exemple: Model.find_by_sql ("SELECT * FROM models WHERE id = 123")la source