Модель Rails найти, где не равно

127

Как мне найти записи в базе данных при неравных условиях? У меня есть это сейчас, но есть ли какой-нибудь способ сделать это на языке рельсов?

GroupUser.where('user_id != ?',me)
Colin
источник
Я думаю, у вас есть хороший способ сделать это в Rails 3.
Spyros

Ответы:

229

В Rails 4.x (см. Http://edgeguides.rubyonrails.org/active_record_querying.html#not-conditions )

GroupUser.where.not(user_id: me)

В Rails 3.x

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

Чтобы сократить длину, вы можете сохранить GroupUser.arel_tableв переменной или, если вы используете внутри самой модели GroupUser, например, в a scope, вы можете использовать arel_table[:user_id]вместоGroupUser.arel_table[:user_id]

Кредит синтаксиса Rails 4.0 для ответа @jbearden

Викрант Чаудхари
источник
А как насчет ассоциаций? - has_many: group_users, -> {where.not (status: "Declined")}, through:: groups, foreign_key: "user_id"
ajbraus
4
GroupUser.where(other_condition: true).where.not(user_id: user_id)
Кстати
26

Единственный способ сделать это лучше - с помощью MetaWhere. .

У MetaWhere есть новый двоюродный брат Squeel, который позволяет использовать такой код:

GroupUser.where{user_id != me}

Само собой разумеется, что если это единственный рефакторинг, который вы собираетесь сделать, не стоит использовать гем, и я бы просто придерживался того, что у вас есть. Squeel полезен в ситуациях, когда у вас есть много сложных запросов, взаимодействующих с кодом Ruby.

Якуб Хампл
источник
4
MetaWhere - это здорово, но эту задачу можно выполнить без добавления гема.
tybro0103
1
@ tybro0103, конечно, задача может быть выполнена (и имхо способ, которым OP делает это прекрасно), вопрос в том, чтобы сделать это более привлекательно. Так что, если вы думаете, что это можно сделать более изящно без драгоценного камня, мне было бы очень интересно, как это сделать.
Jakub Hampl
Ответ Викранта предоставляет решение, не использующее sql или другой драгоценный камень. Но, я исправлюсь, ваш ответ определенно самый удобный для программиста / необычный.
tybro0103
1
добавление драгоценного камня для выполнения такой простой задачи. Удар по москве базукой
baash05 01
Это перебор.
Courtimas
23

Рельсы 4:

Если вы хотите использовать как не равные, так и равные, вы можете использовать:

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

Если вы хотите использовать различные операторы (например >, <), в какой-то момент вы можете захотеть переключить обозначения на следующие:

GroupUser.where("group_id > ? AND user_id != ?", group_id, user_id)
Рик Смит
источник
О чем GroupUser.where(group_id: group_id).where.not(user_id: user_id)?
Энрико Карлессо
@EnricoCarlesso Спасибо за публикацию. Я обновил свой ответ, включив в него ваше предложение. Спасибо.
Рик Смит
9

При работе с ассоциациями всегда следует включать имя таблицы в запрос SQL.

Действительно, если в другой таблице есть user_idстолбец, и вы присоединитесь к обеим таблицам, у вас будет неоднозначное имя столбца в запросе SQL (т.е. проблемы).

Итак, в вашем примере:

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

Или более подробно:

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

Обратите внимание: если вы используете хеш, вам не нужно об этом беспокоиться, потому что Rails позаботится об этом за вас:

GroupUser.where(user: me)

В Rails 4, как сказал @ dr4k3, notбыл добавлен метод запроса :

GroupUser.where.not(user: me)
Damien
источник
6

В Rails 3 я не знаю ничего более интересного. Однако я не уверен, знаете ли вы, что ваше неравное условие не соответствует значениям (user_id) NULL. Если вы этого хотите, вам нужно сделать что-то вроде этого:

GroupUser.where("user_id != ? OR user_id IS NULL", me)
konyak
источник