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.