Se eu tiver um escopo com um lambda e precisar de um argumento, dependendo do valor do argumento, talvez eu saiba que não haverá correspondências, mas ainda quero retornar uma relação, não uma matriz vazia:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
O que eu realmente quero é um método "none", o oposto de "all", que retorna uma relação que ainda pode ser encadeada, mas resulta em curto-circuito na consulta.
ruby-on-rails
activerecord
relation
dzajic
fonte
fonte
Respostas:
Agora existe um mecanismo "correto" no Rails 4:
fonte
Model.scoped
faz o que você está procurando em trilhos 3.Model.none
não funciona. Você precisa usar um de seus nomes reais de modelo, por exemplo,User.none
ou o que você tem.Uma solução mais portátil que não requer uma coluna "id" e não assume que não haverá uma linha com um ID 0:
Ainda estou procurando uma maneira mais "correta".
fonte
scope :none, -> { where("false") }
Chegando no Rails 4
No Rails 4, um encadeamento
ActiveRecord::NullRelation
será retornado de chamadas comoPost.none
.Nem ele nem métodos encadeados gerarão consultas ao banco de dados.
De acordo com os comentários:
Veja o código fonte .
fonte
Você pode adicionar um escopo chamado "none":
Isso fornecerá um ActiveRecord :: Relation vazio
Você também pode adicioná-lo ao ActiveRecord :: Base em um inicializador (se desejar):
Muitas maneiras de obter algo assim, mas certamente não é a melhor coisa a manter em uma base de código. Eu usei o escopo: none ao refatorar e descobrir que preciso garantir um ActiveRecord :: Relation vazio por um curto período de tempo.
fonte
where('1=2')
pode ser um pouco mais concisoModel.none
é assim que você faria isso.É uma solução perigosa porque seu escopo pode estar acorrentado.
User.none.first
retornará o primeiro usuário. É mais seguro usar
fonte
Eu acho que prefiro a aparência das outras opções:
Levando a algo assim:
fonte
where(false)
que não faria o trabalho - ele mantém o escopo inalterado.limit(0)
será substituído se você ligar.first
ou.last
mais tarde na cadeia, pois o Rails será anexadoLIMIT 1
a essa consulta.none
relação mencionada abaixo.Usar escopo:
Mas você também pode simplificar seu código com:
Se você deseja um resultado vazio, use este (remova a condição if):
fonte
É possível e é isso:
http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none
Corrija-me se eu estiver errado.
fonte
Também existem variantes, mas todas elas estão solicitando ao banco de dados
fonte
where(false)
ouwhere(nil)
é simplesmente ignorado.