Modelo do Rails encontra onde não é igual

127

Como posso encontrar registros no meu banco de dados em uma condição não igual? Eu tenho isso agora, mas existe uma maneira sofisticada de falar sobre trilhos?

GroupUser.where('user_id != ?',me)
Colin
fonte
O que você tem é uma boa maneira de fazê-lo, Rails 3, eu acho.
Spyros 24/03

Respostas:

229

No Rails 4.x (consulte http://edgeguides.rubyonrails.org/active_record_querying.html#not-conditions )

GroupUser.where.not(user_id: me)

No Rails 3.x

GroupUser.where(GroupUser.arel_table[:user_id].not_eq(me))

Para encurtar o comprimento, você pode armazenar GroupUser.arel_tableem uma variável ou, se estiver usando dentro do GroupUserpróprio modelo , por exemplo, em a scope, você pode usar em arel_table[:user_id]vez deGroupUser.arel_table[:user_id]

Crédito de sintaxe do Rails 4.0 na resposta de @ jbearden

Vikrant Chaudhary
fonte
E nas associações? - has_many: group_users, -> {where.not (status: "Recusado")}, por meio de: groups, Foreign_key: "user_id"
ajbraus
4
Como nota lateral, ele também funciona bem encadeado:GroupUser.where(other_condition: true).where.not(user_id: user_id)
Enrico Carlesso
38

Trilhos 4

GroupUser.where.not(user_id: me)
jbearden
fonte
26

A única maneira de torná-lo mais sofisticado é com o MetaWhere .

O MetaWhere possui um primo mais novo chamado Squeel, que permite códigos como este:

GroupUser.where{user_id != me}

Escusado será dizer que, se este é o único refator que você vai fazer, não vale a pena usar uma gema e eu gostaria de ficar com o que você tem. Squeel é útil em situações em que você tem muitas consultas complexas interagindo com o código Ruby.

Jakub Hampl
fonte
4
O MetaWhere é ótimo, mas essa tarefa pode ser feita sem a adição de uma gema.
tybro0103
1
@ tybro0103 é claro que a tarefa pode ser executada (e como o OP está funcionando perfeitamente), a questão é fazê-lo mais sofisticado. Então, se você acha que isso pode ser feito sem fantasia, eu estaria muito interessado em como fazer isso.
Jakub Hampl
A resposta da Vikrant fornece uma solução que não envolve sql ou incluindo outra jóia. Mas, permaneço corrigido, sua resposta é definitivamente a mais agradável / agradável para programadores.
tybro0103
1
adicionando uma gema para realizar uma tarefa tão simples. Bater um mozzy com uma bazuca
baash05
Isso é um exagero.
courtimas
23

Trilhos 4:

Se você deseja usar os dois não iguais e iguais, você pode usar:

user_id = 4
group_id = 27
GroupUser.where(group_id: group_id).where.not(user_id: user_id)

Se você quiser usar uma variedade de operadores (por exemplo >, <), em algum momento, poderá mudar as notações para o seguinte:

GroupUser.where("group_id > ? AND user_id != ?", group_id, user_id)
Rick Smith
fonte
Que tal GroupUser.where(group_id: group_id).where.not(user_id: user_id)?
Enrico Carlesso
@EnricoCarlesso Obrigado por postar. Atualizei minha resposta para incluir sua sugestão. Obrigado.
Rick Smith
9

Você sempre deve incluir o nome da tabela na consulta SQL ao lidar com associações.

De fato, se outra tabela tiver a user_idcoluna e você juntar essas duas tabelas, terá um nome de coluna ambíguo na consulta SQL (ou seja, problemas).

Então, no seu exemplo:

GroupUser.where("groups_users.user_id != ?", me)

Ou um pouco mais detalhado:

GroupUser.where("#{table_name}.user_id IS NOT ?", me)

Observe que se você estiver usando um hash, não precisará se preocupar com isso, porque o Rails cuida disso para você:

GroupUser.where(user: me)

No Rails 4, como dito por @ dr4k3, o método de consulta notfoi adicionado:

GroupUser.where.not(user: me)
Damien
fonte
6

No Rails 3, não conheço nada mais sofisticado. No entanto, não tenho certeza se você está ciente, sua condição não igual não corresponde aos valores (user_id) NULL. Se você quiser isso, terá que fazer algo assim:

GroupUser.where("user_id != ? OR user_id IS NULL", me)
konyak
fonte