¿Orden de clasificación predeterminado para un modelo rails?


Me gustaría especificar un orden de clasificación predeterminado en mi modelo.

De modo que cuando hago un .where() sin especificar un .order() utiliza la ordenación predeterminada. Pero si especifico un .order(), anula el valor predeterminado.

Author: Kara, 2010-08-03

3 answers

default_scope

Esto funciona para Rails 4+:

class Book < ActiveRecord::Base
  default_scope { order(created_at: :desc) }
end

Para Rails 2.3, 3, necesita esto en su lugar:

default_scope order('created_at DESC')

Para los carriles 2.x:

default_scope :order => 'created_at DESC'

Donde created_at es el campo en el que desea que se realice la ordenación predeterminada.

Nota: ASC es el código que uso para subir y DESC es descendente (desc, NO dsc !).

scope

Una vez que esté acostumbrado a eso, también puede usar scope:

class Book < ActiveRecord::Base
  scope :confirmed, :conditions => { :confirmed => true }
  scope :published, :conditions => { :published => true }
end

Para Rails 2 necesitas named_scope.

:published el alcance le da Book.published en lugar de Book.find(:published => true).

Desde Rails 3 puedes 'encadenar' esos métodos concatenándolos con puntos entre ellos, por lo que con los ámbitos anteriores ahora puedes usar Book.published.confirmed.

Con este método, la consulta no se ejecuta realmente hasta que se necesitan resultados reales (evaluación perezosa), por lo que 7 ámbitos podrían encadenarse entre sí, pero solo resulta en 1 consulta de base de datos real, para evitar problemas de rendimiento al ejecutar 7 consultas separadas.

Puede usar un parámetro pasado como una fecha o un user_id (algo que cambiará en tiempo de ejecución y por lo tanto necesitará esa 'evaluación perezosa', con una lambda, como esta:

scope :recent_books, lambda 
  { |since_when| where("created_at >= ?", since_when) }
  # Note the `where` is making use of AREL syntax added in Rails 3.

Finalmente puede deshabilitar el ámbito predeterminado con:

Book.with_exclusive_scope { find(:all) } 

O incluso mejor:

Book.unscoped.all

Que deshabilitará cualquier filtro (condiciones) u ordenar (ordenar por).

Tenga en cuenta que la primera versión funciona en Rails2+ mientras que el el segundo (sin codificar) es solo para Rails3 +


So ... si estás pensando, hmm, así que estos son como los métodos entonces... Sí, eso es exactamente lo que son estos alcances.
Son como tener def self.method_name ...code... end pero como siempre con ruby son pequeños atajos sintácticos agradables (o' azúcar') para hacer las cosas más fáciles para usted!

De hecho, son métodos a nivel de clase, ya que operan en el conjunto 1 de 'todos' registros.

Su formato está cambiando sin embargo, con rails 4 hay una advertencia de desaprobación cuando se usa # scope sin pasar un objeto llamable. Por ejemplo ámbito :rojo, donde(color: 'rojo') debe cambiarse a scope :red, -> { where(color: 'red') }.

Como nota al margen, cuando se usa incorrectamente, default_scope puede ser mal utilizado/abusado.
Esto se trata principalmente de cuándo se usa para acciones como where limitando (filtrando) la selección default (una mala idea para un default) en lugar de solo usarse para ordenar resultados.
Para where selecciones, simplemente use los ámbitos con nombre regular. y agregue ese ámbito en la consulta, por ejemplo, Book.all.published donde published es un ámbito con nombre.

En conclusión, los alcances son realmente geniales y le ayudan a impulsar las cosas en el modelo para un enfoque de secador de "controlador delgado de modelo gordo".

 485
Author: Michael Durrant,
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
2016-11-02 15:42:38

Una actualización rápida de la excelente respuesta de Michael anterior.

Para Rails 4.0 + necesitas poner tu orden en un bloque como este:

class Book < ActiveRecord::Base
  default_scope { order('created_at DESC') }
end

Observe que la instrucción order se coloca en un bloque denotado por las llaves.

Lo cambiaron porque era demasiado fácil pasar algo dinámico (como el tiempo actual). Esto elimina el problema porque el bloque se evalúa en tiempo de ejecución. Si no usas un bloque obtendrás este error:

Soporte para llamadas # default_scope sin un bloque se elimina. Por ejemplo, en lugar de default_scope where(color: 'red'), utilice default_scope { where(color: 'red') }. (Alternativamente, puede redefinirse a sí mismo.default_scope.)

Como @Dan menciona en su comentario a continuación, puedes hacer una sintaxis más rubí como esta:

class Book < ActiveRecord::Base
  default_scope { order(created_at: :desc) }
end

O con múltiples columnas:

class Book < ActiveRecord::Base
  default_scope { order({begin_date: :desc}, :name) }
end

Gracias @Dan !

 105
Author: Paul Oliver,
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:26

Puede usar default_scope para implementar un orden de clasificación predeterminado http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html

 6
Author: Slobodan Kovacevic,
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-03-18 22:19:30