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)
Colin
źródło
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

Vikrant Chaudhary
źródło
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
38

Szyny 4

GroupUser.where.not(user_id: me)
jbearden
źródło
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.

Jakub Hampl
źródło
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)
Rick Smith
źródło
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)
Damien
źródło
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)
konyak
źródło