Sobreescribir un ámbito predeterminado de Rails
Si tengo un modelo ActiveRecord:: Base con un ámbito predeterminado:
class Foo < ActiveRecord::Base
default_scope :conditions => ["bar = ?",bar]
end
¿Hay alguna manera de hacer un Foo.find
¿sin usando las condiciones default_scope
? En otras palabras, ¿puede anular un ámbito predeterminado?
Habría pensado que usar 'default' en el nombre sugeriría que era overridable, de lo contrario se llamaría algo así como global_scope
, ¿verdad?
8 answers
Respuesta corta: No uses default_scope
a menos que realmente tengas que hacerlo. Probablemente estarás mejor con alcances con nombre. Dicho esto, puede usar with_exclusive_scope
para anular el ámbito predeterminado si es necesario.
Echa un vistazo a esta pregunta para más detalles.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:48
En los carriles 3:
foos = Foo.unscoped.where(:baz => baz)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-17 15:04:37
Si todo lo que necesita es cambiar el orden definido en default_scope
, puede usar reorder
método .
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-12 12:26:45
Desde 4.1
puede utilizar ActiveRecord::QueryMethods#unscope
para combatir el ámbito 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
Es actualmente posible unscope
cosas como: :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having
.
Pero aún así por favor evite usar default_scope
si puede. Es por tu propio bien.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-16 14:03:45
Puede anular un ámbito predeterminado utilizando el método with_exclusive_scope
. Entonces:
foos = Foo.with_exclusive_scope { :conditions => ["baz = ?", baz] }
-
with_exclusive_scope
documentación
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-02 00:31:47
Rails 3 default_scope no parece ser anulado como en Rails 2.
Por ejemplo
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 ámbito predeterminado GANA. Estoy eliminando todos mis default_scopes y codificándolo explícitamente en todas partes.
Trampas Rails3!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-16 02:04:50
Con Rails 3 + se puede usar una combinación de unscoped y merge:
# 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-13 07:44:19
Bueno, siempre puedes usar el antiguo favorito find_by_sql
con la consulta completa.
Por ejemplo:
Modelo.find_by_sql ("SELECT * FROM models WHERE id=123")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-26 10:49:21