Модель рейок знайти там, де немає рівних


127

Як я можу знайти записи в своїй базі даних за нерівних умов? У мене це є зараз, але чи є химерні рейки - говорять про це?

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

Що у вас є, це гарно хороший спосіб Rails 3, як я думаю.
Спірос

Відповіді:


229

У Rails 4.x (див. Http://edgeguides.rubyonrails.org/active_record_querying.html#not-conditions )

GroupUser.where.not(user_id: me)

У рейках 3.x

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

Щоб скоротити довжину, ви можете зберігати GroupUser.arel_tableзмінну або, якщо ви використовуєте всередині самої моделі GroupUser, наприклад, у scope, ви можете використовувати arel_table[:user_id]замістьGroupUser.arel_table[:user_id]

Синтаксичний рейтинг 4.0 на відповідь @ jbearden


А як щодо асоціацій? - has_many: group_users, -> {where.not (статус: "Відхилено")}, через:: 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 Звичайно, завдання можна виконати (а так, як це робить ОП - це зовсім чудово), питання в тому, щоб зробити це більш фантастично. Тож якщо ви думаєте, що це можна зробити більш фантазійним без дорогоцінного каміння, я був би дуже зацікавлений, як це зробити.
Якуб Гампл

Відповідь Вікранта передбачає, що рішення не передбачає sql або включення іншого дорогоцінного каміння. Але, я виправданий, ваша відповідь, безумовно, найбільш зручна / кохана.
tybro0103

1
додавши дорогоцінний камінь для виконання такого простого завдання. Ударити мозі базукою
baash05

Це надмірність.
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.