Se eu tiver um modelo ActiveRecord :: Base com um escopo padrão:
class Foo < ActiveRecord::Base
default_scope :conditions => ["bar = ?",bar]
end
Existe alguma maneira de fazer um Foo.find
sem usar as default_scope
condições? Em outras palavras, você pode substituir um escopo padrão?
Eu teria pensado que o uso de 'default' no nome sugeriria que fosse substituível, caso contrário, seria chamado de algo como global_scope
, certo?
ruby-on-rails
Gareth
fonte
fonte
Respostas:
Resposta curta: Não use a
default_scope
menos que você realmente precise. Você provavelmente estará melhor com escopos nomeados. Com isso dito, você podewith_exclusive_scope
substituir o escopo padrão, se necessário.Dê uma olhada nesta pergunta para obter mais detalhes.
fonte
default_scope
pode parecer uma boa ideia, mas provavelmente causará várias dores de cabeça durante a vida útil do seu aplicativo.with_exclusive_scope
foi removido nos trilhos 3default_scope
é uma excelente ferramenta e há situações em que você poderia outra maneira, masdefault_scope
é a coisa certa a fazer. Por exemplo, quando você tem umProduct
modelo que tem uminactive
sinalizador, definir adefault_scope { where inactive: false }
é a melhor coisa a fazer, uma vez que 99% ou casos você não deseja exibir um produto inativo. Depois, basta chamarunscoped
os casos restantes de 1%, que provavelmente é um painel do administrador.No Rails 3:
fonte
def self.random; unscoped.order('rand()'); end
unscoped remove ALL sql antes dele, não apenas o que está listado em default_scope. Embora tecnicamente uma resposta correta, tenha cuidado usandounstopped
unscoped
quando ele pode seguir diretamente um modelo, por exemplo,Foo.unscoped.blah()
está ok, mas nuncaFoo.blah().unscoped
.Se tudo que você precisa é mudar a ordem definida em
default_scope
, você pode usar oreorder
método .executa o seguinte SQL:
fonte
scope :without_default_order, -> { reorder("") }
e você pode fazer coisas como:Foo.without_default_order.order("created_at ASC")
Em algumas situações, ele lê melhor (talvez não seja exatamente essa situação, mas eu tive uma).Como
4.1
você pode usarActiveRecord::QueryMethods#unscope
para combater o escopo padrão:Atualmente, é possível
unscope
coisas como::where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having
.Mas ainda assim evite usar
default_scope
se puder . É para o seu próprio bem.fonte
Você pode substituir um escopo padrão usando o
with_exclusive_scope
método Assim:with_exclusive_scope
documentaçãofonte
O default_scope do Rails 3 não parece ser substituído, como ocorreu no Rails 2.
por exemplo
No meu aplicativo, usando o PostgreSQL, a ordem no escopo padrão WINS. Estou removendo todos os meus default_scopes e codificando-os explicitamente em todos os lugares.
Pitfall Rails3!
fonte
Bar.foos.reorder(:created_at => :asc)
Com o Rails 3+, você pode usar uma combinação de sem escopo e mesclagem:
fonte
User.unscoped.where(email: "[email protected]")
No Rails 5.1 ou posterior (e talvez antes, mas já testei que funciona no 5.1), é possível remover uma coluna específica, que é a solução ideal para remover a
default_scope
de uma maneira que possa ser usada dentro de um escopo nomeado. No caso dos POdefault_scope
,Ou
Ambos resultarão em uma consulta sql que não aplica o escopo original, mas aplica quaisquer outras condições que sejam mescladas no arel.
fonte
Bem, você sempre pode usar o favorito dos velhos tempos
find_by_sql
com a consulta completa. Por exemplo: Model.find_by_sql ("SELECT * FROM models WHERE id = 123")fonte