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


127

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

GroupUser.where('user_id != ?',me)

Я думаю, у вас есть хороший способ сделать это в 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)

6

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

GroupUser.where("user_id != ? OR user_id IS NULL", me)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.