ruby on rails - software - Anulando un valor predeterminado de Rails
ruby on rails tutorial (8)
Bueno, siempre puedes usar el favorito de siempre find_by_sql
con la consulta completa. Por ejemplo: Model.find_by_sql ("SELECT * FROM models WHERE id = 123")
Si tengo un modelo ActiveRecord :: Base con un alcance predeterminado:
class Foo < ActiveRecord::Base
default_scope :conditions => ["bar = ?",bar]
end
¿Hay alguna forma de hacer un Foo.find
sin usar las condiciones de default_scope
? En otras palabras, ¿puede anular un alcance predeterminado?
Hubiera pensado que usar ''predeterminado'' en el nombre sugeriría que era invalidable, de lo contrario se llamaría algo así como global_scope
, ¿verdad?
Con Rails 3+ puedes usar una combinación de no combinado y fusionar:
# model User has a default scope
query = User.where(email: "[email protected]")
# get rid of default scope and then merge the conditions
query = query.unscoped.merge(query)
Desde 4.1
, puede usar ActiveRecord::QueryMethods#unscope
para combatir el alcance predeterminado:
class User < ActiveRecord::Base
default_scope { where tester: false }
scope :testers, -> { unscope(:where).where tester: true }
scope :with_testers, -> { unscope(:where).where tester: [true, false] }
# ...
end
Actualmente es posible unscope
como:: :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having
unscope
de unscope
:where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having
.
Pero aún así , evite el uso de default_scope
si puede . Es por tu propio bien.
En Rails 3:
foos = Foo.unscoped.where(:baz => baz)
Puede anular un alcance predeterminado utilizando el método with_exclusive_scope
. Asi que:
foos = Foo.with_exclusive_scope { :conditions => ["baz = ?", baz] }
-
with_exclusive_scope
documentación_s_exclusive_scope
Rails 3 default_scope no parece anulado como lo hizo en Rails 2.
p.ej
class Foo < ActiveRecord::Base
belongs_to :bar
default_scope :order=>"created_at desc"
end
class Bar < ActiveRecord::Base
has_many :foos
end
> Bar.foos
SELECT * from Foo where bar_id = 2 order by "created_at desc";
> Bar.unscoped.foos
SELECT * from Foo; (WRONG! removes the "has" relationship)
> Bar.foos( :order=>"created_at asc" ) # trying to override ordering
SELECT * from Foo where bar_id = 2 order by "created_at desc, created_at asc"
En mi aplicación, usando PostgreSQL, el orden en el alcance predeterminado WINS. Estoy eliminando todos mis métodos predeterminados y codificándolo explícitamente en todas partes.
Pitfall Rails3!
Respuesta corta: no uses default_scope
menos que realmente tengas que hacerlo. Probablemente será mejor con ámbitos con nombre. Dicho esto, puede usar with_exclusive_scope
para anular el alcance predeterminado si es necesario.
Eche un vistazo a esta pregunta para más detalles.
Si todo lo que necesita es cambiar el orden definido en default_scope
, puede usar el método de reorder
.
class Foo < ActiveRecord::Base
default_scope order(''created_at desc'')
end
Foo.reorder(''created_at asc'')
ejecuta el siguiente SQL:
SELECT * FROM "foos" ORDER BY created_at asc