Model szyn znajdź, gdzie nie jest równy


128

Jak mogę znaleźć rekordy w mojej bazie danych o nierównym stanie? Mam to teraz, ale czy jest jakiś fantazyjny sposób na to, aby to zrobić?

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

Myślę, że to, co masz, jest dobrym sposobem na zrobienie tego w Railsach 3.
— Spyros,

Odpowiedzi:


230

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

GroupUser.where.not(user_id: me)

W Rails 3.x

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

Aby skrócić długość, możesz zapisać GroupUser.arel_tablew zmiennej lub jeśli używasz wewnątrz samego modelu GroupUser, np. W a scope, możesz użyć arel_table[:user_id]zamiastGroupUser.arel_table[:user_id]

Kredyt składni Rails 4.0 do odpowiedzi @ jbearden


A co ze stowarzyszeniami? - has_many: group_users, -> {where.not (status: "Odrzucono")}, przez:: groups, Foreign_key: "user_id"
— ajbraus

4
Na marginesie, działa również dobrze przykuty:GroupUser.where(other_condition: true).where.not(user_id: user_id)
— Enrico Carlesso


27

Jedynym sposobem, aby uzyskać bardziej wyrafinowany wygląd, jest MetaWhere .

MetaWhere ma nowszego kuzyna, który nazywa się Squeel, który umożliwia taki kod:

GroupUser.where{user_id != me}

Jest rzeczą oczywistą, że jeśli jest to jedyny refaktor, który zamierzasz wykonać, nie warto używać klejnotu i po prostu trzymałbym się tego, co masz. Squeel jest przydatny w sytuacjach, gdy masz wiele złożonych zapytań współdziałających z kodem Rubiego.


4
MetaWhere jest świetny, ale to zadanie można wykonać bez dodawania klejnotu.
— tybro0103

1
@ tybro0103 oczywiście zadanie można wykonać (a imho sposób, w jaki OP to robi, jest w porządku), pytanie dotyczy zrobienia tego bardziej wyszukanego. Więc jeśli uważasz, że można to zrobić bardziej wyszukane bez klejnotu, byłbym bardzo zainteresowany, jak to zrobić.
— Jakub Hampl

Odpowiedź Vikranta zapewnia rozwiązanie, które nie obejmuje sql ani innego klejnotu. Ale, mam rację, twoja odpowiedź jest zdecydowanie najbardziej przyjazna dla programistów / wymyślna.
— tybro0103

1
dodanie klejnotu, aby wykonać tak proste zadanie. Uderzenie w mozzy bazooką
— baash 05

To przesada.
— courimas

23

Szyny 4:

Jeśli chcesz użyć zarówno nierównych, jak i równych, możesz użyć:

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

Jeśli chcesz używać różnych operatorów (np. >, <), W pewnym momencie możesz chcieć przełączyć zapisy na następujące:

GroupUser.where("group_id > ? AND user_id != ?", group_id, user_id)

O co chodzi GroupUser.where(group_id: group_id).where.not(user_id: user_id)?
— Enrico Carlesso

@EnricoCarlesso Dzięki za wysłanie wiadomości. Zaktualizowałem moją odpowiedź, aby zawierała twoją sugestię. Dzięki.
— Rick Smith

9

W przypadku asocjacji należy zawsze uwzględniać nazwę tabeli w zapytaniu SQL.

Rzeczywiście, jeśli inna tabela ma user_idkolumnę i dołączysz do obu tabel, będziesz miał niejednoznaczną nazwę kolumny w zapytaniu SQL (tj. Kłopoty).

A więc w twoim przykładzie:

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

Lub bardziej szczegółowe:

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

Zauważ, że jeśli używasz hasha, nie musisz się tym martwić, ponieważ Railsy zajmują się tym za Ciebie:

GroupUser.where(user: me)

W Rails 4, jak powiedział @ dr4k3, notdodano metodę zapytania :

GroupUser.where.not(user: me)

6

W Rails 3 nie znam nic bardziej wyszukanego. Jednak nie jestem pewien, czy wiesz, że twój warunek nierówności nie pasuje do wartości NULL (user_id). Jeśli chcesz, będziesz musiał zrobić coś takiego:

GroupUser.where("user_id != ? OR user_id IS NULL", me)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.