Estou tentando encontrar todos os usuários com um ID maior que 200, mas estou tendo problemas com a sintaxe específica.
User.where(:id > 200)
e
User.where("? > 200", :id)
ambos falharam.
Alguma sugestão?
ruby-on-rails
syntax
where
Adam Templeton
fonte
fonte
?
, em vez de incluir o200
?Eu só testei isso no Rails 4, mas há uma maneira interessante de usar um intervalo com um
where
hash para obter esse comportamento.irá gerar o SQL
O mesmo pode ser feito por menos do que com
-Float::INFINITY
.Acabei de postar uma pergunta semelhante sobre como fazer isso com datas aqui no SO .
>=
vs>
Para evitar que as pessoas tenham que pesquisar e acompanhar a conversa de comentários, aqui estão os destaques.
O método acima gera apenas uma
>=
consulta e não a>
. Existem muitas maneiras de lidar com essa alternativa.Para números discretos
Você pode usar uma
number_you_want + 1
estratégia como a acima, onde me interesso por usuários,id > 200
mas na verdade procuroid >= 201
. Isso é bom para números inteiros e números em que você pode incrementar por uma única unidade de interesse.Se você tiver o número extraído em uma constante bem nomeada, isso pode ser o mais fácil de ler e entender rapidamente.
Lógica invertida
Podemos usar o fato de que
x > y == !(x <= y)
e usar a cadeia where not.que gera o SQL
Isso leva um segundo extra para ler e refletir, mas funcionará para valores ou colunas não discretos, nos quais você não pode usar a
+ 1
estratégia.Mesa Arel
Se você quiser se divertir, pode usar o
Arel::Table
.irá gerar o SQL
Os detalhes são os seguintes:
Essa abordagem fornece o SQL exato em que você está interessado, mas poucas pessoas usam a tabela Arel diretamente e podem achar que é confusa e / ou confusa. Você e sua equipe saberão o que é melhor para você.
Bônus
A partir do Rails 5, você também pode fazer isso com datas!
irá gerar o SQL
Bônus Duplo
Depois que o Ruby 2.6 for lançado (25 de dezembro de 2018), você poderá usar a nova sintaxe de alcance infinito! Em vez de
201..Float::INFINITY
você será capaz de escrever201..
. Mais informações nesta postagem do blog .fonte
where
fósforos básicos . Pois>
eu sugiro usar um>= (number_you_want + 1)
para simplicidade. Se você realmente deseja garantir que seja apenas uma>
consulta, pode acessar a tabela ARel. Toda classe que herda deActiveRecord
possui umarel_table
método getter que retorna o valorArel::Table
dessa classe. As colunas na tabela são acessadas com o[]
método likeUser.arel_table[:id]
. Isso retorna eArel::Attributes::Attribute
você pode ligargt
e transmitir200
. Isso pode ser passado parawhere
. por exemploUser.where(User.arel_table[:id].gt(200))
.User.where(created_at: 3.days.ago..DateTime::Infinity.new)
.WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)
(marcações em volta dos nomes de tabelas e colunas omitidos para formatação de comentários de SO).Um uso melhor é criar um escopo no modelo de usuário
where(arel_table[:id].gt(id))
fonte
Se você deseja uma escrita mais intuitiva, existe uma gema chamada squeel que permitirá que você escreva suas instruções assim:
Observe os caracteres 'chave' {} e
id
sendo apenas um texto.Tudo o que você precisa fazer é adicionar um squeel ao seu Gemfile:
Isso pode facilitar muito sua vida ao escrever instruções SQL complexas em Ruby.
fonte
Arel é seu amigo.
fonte
Outra possibilidade chique é ...
Esse recurso permite criar consultas mais compreensíveis se você deseja substituir em vários locais, por exemplo ...
Isso tem mais significado do que ter muito
?
na consulta ...fonte
Muitas vezes tenho esse problema com os campos de data (onde os operadores de comparação são muito comuns).
Para aprofundar a resposta de Mihai, que acredito ser uma abordagem sólida.
Para os modelos, você pode adicionar escopos como este:
... e depois no seu controlador, ou onde quer que você esteja usando o seu modelo:
... um exemplo mais complexo com junções se parece com isso:
Uma grande vantagem dessa abordagem é (a) permitir compor suas consultas de diferentes escopos e (b) evitar colisões de alias quando você ingressar na mesma tabela duas vezes, já que o arel_table tratará essa parte da geração de consultas.
fonte
Rails 6.1+
O Rails 6.1 adicionou uma nova 'sintaxe' para operadores de comparação em
where
condições, por exemplo:Portanto, sua consulta pode ser reescrita da seguinte maneira:
Aqui está um link para o PR, onde você pode encontrar mais exemplos.
fonte
Mais curta:
fonte
where("id > ?", 200)
sintaxe). Isso não consegue isso.