Me gustaría especificar un orden de clasificación predeterminado en mi modelo.
De modo que cuando hago un .where()
sin especificar un .order()
, usa el tipo predeterminado. Pero si especifico un .order()
, anula el valor predeterminado.
Me gustaría especificar un orden de clasificación predeterminado en mi modelo.
De modo que cuando hago un .where()
sin especificar un .order()
, usa el tipo predeterminado. Pero si especifico un .order()
, anula el valor predeterminado.
Respuestas:
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 Rails 2.x:
default_scope :order => 'created_at DESC'
¿Dónde created_at
está el campo en el que desea que se realice la ordenación predeterminada?
Nota: ASC es el código que se utilizará para ascendente y DESC es para 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
alcance te da en Book.published
lugar de
Book.find(:published => true)
.
Desde Rails 3 puede 'encadenar' esos métodos juntos concatenando con puntos entre ellos, por lo que con los ámbitos anteriores ahora puede usar Book.published.confirmed
.
Con este método, la consulta no se ejecuta realmente hasta que se necesitan resultados reales (evaluación diferida), por lo que se podrían encadenar 7 ámbitos pero solo dar como resultado 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 diferida', 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 alcance predeterminado con:
Book.with_exclusive_scope { find(:all) }
o 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 la segunda (sin ámbito) es solo para Rails3 +
Entonces
... si estás pensando, hmm, entonces estos son como métodos, entonces ... ¡sí, eso es exactamente lo que son estos ámbitos!
Son como tener, def self.method_name ...code... end
pero como siempre con el rubí, son pequeños atajos sintácticos (o 'azúcar') para hacerte las cosas más fáciles.
De hecho, son métodos de nivel de clase, ya que operan en el 1 conjunto de registros 'todos'.
Sin embargo, su formato está cambiando, con los rieles 4 hay una advertencia de desaprobación cuando se usa #scope sin pasar un objeto invocable. Por ejemplo, alcance: rojo, donde (color: 'rojo') debe cambiarse a scope :red, -> { where(color: 'red') }
.
Como nota al margen, cuando se usa incorrectamente, el _scope predeterminado puede ser mal utilizado / abusado.
Esto se trata principalmente cuando se utiliza para acciones como where
limitar (filtrar) la selección predeterminada (una mala idea para un valor predeterminado) en lugar de simplemente usarse para ordenar resultados.
Para las where
selecciones, solo use los ámbitos con nombre normal. y agregue ese alcance en la consulta, por ejemplo, Book.all.published
dónde published
es un alcance con nombre.
En conclusión, los alcances son realmente geniales y lo ayudan a impulsar las cosas dentro del modelo para un enfoque SECO de 'controlador delgado de modelo grueso'.
default_scope { order("#{table_name}.created_at DESC") }
?
default_scope { order(created_at: :desc) }
4.2.6
parece ordenar por updated_at
no created_at
.
updated_at
por defecto? : - |
Una actualización rápida a la excelente respuesta de Michael anterior.
Para Rails 4.0+ necesitas poner tu clasificación en un bloque como este:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
Observe que la declaración de orden se coloca en un bloque denotado por las llaves.
Lo cambiaron porque era demasiado fácil pasar algo dinámico (como la hora actual). Esto elimina el problema porque el bloque se evalúa en tiempo de ejecución. Si no usa un bloque, obtendrá este error:
Se elimina la compatibilidad para llamar a #default_scope sin un bloque. Por ejemplo, en lugar de
default_scope where(color: 'red')
, por favor usedefault_scope { where(color: 'red') }
. (Alternativamente, puede redefinir self.default_scope).
Como @Dan menciona en su comentario a continuación, puede 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 !
default_scope { order(created_at: :desc) }
si, como yo, intentara minimizar la sintaxis sql en los rieles. <br/> Si tiene varias columnas para ordenar y desea usar la nueva sintaxis, es posible que necesite ajustar la desc. columnas con bigotes como estedefault_scope { order({begin_date: :desc}, :name) }
Puede usar default_scope para implementar un orden de clasificación predeterminado http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html
default_scope
de esa página, ya que se ha rediseñado desde ActiveRecord::Base
dentro ActiveRecord::Scoping::Default::ClassMethods
( api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/... )