Модель 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.