Gostaria de especificar uma ordem de classificação padrão no meu modelo.
Assim, quando eu faço um .where()sem especificar um, .order()ele usa a classificação padrão. Mas se eu especificar um .order(), ele substituirá o padrão.
Gostaria de especificar uma ordem de classificação padrão no meu modelo.
Assim, quando eu faço um .where()sem especificar um, .order()ele usa a classificação padrão. Mas se eu especificar um .order(), ele substituirá o padrão.
Respostas:
default_scopeIsso funciona para o Rails 4+:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
Para o Rails 2.3, 3, você precisa disso:
default_scope order('created_at DESC')
Para o Rails 2.x:
default_scope :order => 'created_at DESC'
Onde created_até o campo no qual você deseja que a classificação padrão seja feita.
Nota: ASC é o código a ser usado para Crescente e DESC é para decrescente ( desc, NÃO dsc !).
scopeDepois de se acostumar, você também pode usar scope:
class Book < ActiveRecord::Base
scope :confirmed, :conditions => { :confirmed => true }
scope :published, :conditions => { :published => true }
end
Para o Rails 2, você precisa named_scope.
:publishedescopo fornece a você em Book.publishedvez de
Book.find(:published => true).
Desde o Rails 3, você pode 'encadear' esses métodos, concatenando-os com períodos entre eles; portanto, com os escopos acima, agora você pode usar Book.published.confirmed.
Com esse método, a consulta não é realmente executada até que os resultados reais sejam necessários (avaliação lenta); portanto, 7 escopos podem ser encadeados, mas resultando apenas em 1 consulta real no banco de dados, para evitar problemas de desempenho ao executar 7 consultas separadas.
Você pode usar um parâmetro passado como uma data ou um user_id (algo que será alterado no tempo de execução e, portanto, precisará dessa 'avaliação lenta', com um lambda, assim:
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, você pode desativar o escopo padrão com:
Book.with_exclusive_scope { find(:all) }
ou melhor ainda:
Book.unscoped.all
que desativará qualquer filtro (condições) ou classificação (ordenar por).
Observe que a primeira versão funciona no Rails2 +, enquanto a segunda (sem escopo) é apenas para o Rails3 +
Então
... se você está pensando, hmm, então esses são apenas métodos, então ... sim, é exatamente isso que esses escopos são!
Eles são como ter, def self.method_name ...code... endmas como sempre com ruby, são pequenos atalhos sintáticos (ou "açúcar") para facilitar as coisas para você!
Na verdade, eles são métodos de nível de classe, pois operam no conjunto 1 de 'todos' registros.
Seu formato está mudando, no entanto, com os trilhos 4, há aviso de reprovação ao usar #scope sem passar um objeto que pode ser chamado. Por exemplo, scope: red, onde (color: 'red') deve ser alterado para scope :red, -> { where(color: 'red') }.
Como observação, quando usado incorretamente, o _scope padrão pode ser mal utilizado / abusado.
Isso ocorre principalmente quando é usado para ações como wherelimitar (filtrar) a seleção padrão (uma má idéia para um padrão), em vez de apenas ser usado para ordenar resultados.
Para whereseleções, basta usar os escopos nomeados regulares. e adicione esse escopo na consulta, por exemplo, Book.all.publishedonde publishedestá um escopo nomeado.
Em conclusão, os escopos são realmente ótimos e ajudam você a inserir as coisas no modelo para uma abordagem DRYer de 'modelo fino de controlador de gordura'.
default_scope { order("#{table_name}.created_at DESC") }?
default_scope { order(created_at: :desc) }
4.2.6parece classificar por updated_atnão created_at.
updated_atpor padrão? : - |
Uma atualização rápida da excelente resposta de Michael acima.
Para o Rails 4.0+, você precisa colocar sua classificação em um bloco como este:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
Observe que a declaração de ordem é colocada em um bloco indicado pelas chaves.
Eles mudaram porque era muito fácil transmitir algo dinâmico (como a hora atual). Isso remove o problema porque o bloco é avaliado em tempo de execução. Se você não usar um bloco, receberá este erro:
O suporte para chamar #default_scope sem um bloco foi removido. Por exemplo, em vez de
default_scope where(color: 'red'), por favor usedefault_scope { where(color: 'red') }. (Como alternativa, você pode apenas redefinir self.default_scope.)
Como @Dan menciona em seu comentário abaixo, você pode fazer uma sintaxe mais rubyish como esta:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
ou com várias colunas:
class Book < ActiveRecord::Base
default_scope { order({begin_date: :desc}, :name) }
end
Obrigado @Dan !
default_scope { order(created_at: :desc) }se você tentasse minimizar a sintaxe sql nos rails. <br/> Se você tem várias colunas para ordenar e deseja usar a nova sintaxe, pode ser necessário agrupar a descrição desc. colunas em bigodes como estedefault_scope { order({begin_date: :desc}, :name) }
Você pode usar o default_scope para implementar uma ordem de classificação padrão http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html
default_scopenessa página, porque foi reformulado a partir de ActiveRecord::Basedentro ActiveRecord::Scoping::Default::ClassMethods( api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/... )