Rails where condition using NOT NULL
Używając stylu rails 3 jak miałbym napisać przeciwieństwo:
Foo.includes(:bar).where(:bars=>{:id=>nil})
Chcę znaleźć, gdzie id nie jest null. Próbowałem:
Foo.includes(:bar).where(:bars=>{:id=>!nil}).to_sql
Ale to zwraca:
=> "SELECT \"foos\".* FROM \"foos\" WHERE (\"bars\".\"id\" = 1)"
To zdecydowanie nie jest to, czego potrzebuję, i wydaje się prawie jak robal w ARel. 5 answers
Kanoniczny sposób na zrobienie tego z Rails 3:
Foo.includes(:bar).where("bars.id IS NOT NULL")
ActiveRecord 4.0 i wyżej dodaje where.not
więc możesz to zrobić:
Foo.includes(:bar).where.not('bars.id' => nil)
Foo.includes(:bar).where.not(bars: { id: nil })
Podczas pracy z zakresami między tabelami, wolę wykorzystać merge
żebym mógł łatwiej korzystać z istniejących zakresów.
Foo.includes(:bar).merge(Bar.where.not(id: nil))
Również, ponieważ includes
nie zawsze wybiera strategię join, należy użyć references
tutaj również, w przeciwnym razie możesz skończyć z nieprawidłowym SQL.
Foo.includes(:bar)
.references(:bar)
.merge(Bar.where.not(id: nil))
Już nie zaleca się użycie Squeel do tego celu, ponieważ nie zawsze ma on opiekuna na pełny etat i zależy to od prywatnych API, które powodują częste łamanie zmian.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-11 02:44:50
To nie błąd w Arelu, to błąd w Twojej logice.
To czego tu chcesz to:
Foo.includes(:bar).where(Bar.arel_table[:id].not_eq(nil))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-23 03:53:14
Dla Kolejek4:
Więc to, czego chcesz, to wewnętrzne połączenie, więc naprawdę powinieneś użyć predykatu joins: {]}
Foo.joins(:bar)
Select * from Foo Inner Join Bars ...
Ale, dla przypomnienia, jeśli chcesz warunek "NOT NULL" po prostu użyj predykatu not:
Foo.includes(:bar).where.not(bars: {id: nil})
Select * from Foo Left Outer Join Bars on .. WHERE bars.id IS NOT NULL
Zauważ, że ta składnia zgłasza deprecjację (mówi o fragmencie string SQL, ale domyślam się, że warunek hash został zmieniony na string w parserze?), więc pamiętaj, aby dodać odwołania do końca:
Foo.includes(:bar).where.not(bars: {id: nil}).references(:bar)
Ostrzeżenie: wygląda jak jesteś chętny Ładowanie tabeli (s) (jeden z dnia: ....), do których odwołuje się ciąg znaków SQL. Na przykład:
Post.includes(:comments).where("comments.title = 'foo'")
Obecnie Active Record rozpoznaje tabelę w łańcuchu i zna aby dołączyć tabelę komentarzy do zapytania, zamiast wczytywać komentarze w osobnym zapytaniu. Jednak robiąc to bez pisania pełnowymiarowego Parser SQL jest z natury wadliwy. Ponieważ nie chcemy pisać SQL parser, usuwamy tę funkcjonalność. Od teraz musisz jawnie informuj rekord aktywny, gdy odwołujesz się do tabeli z string:
Post.includes(:comments).where("comments.title = 'foo'").references(:comments)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-06 18:36:25
Z Rails 4 to proste:
Foo.includes(:bar).where.not(bars: {id: nil})
Zobacz: http://guides.rubyonrails.org/active_record_querying.html#not-conditions
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-08 06:12:36
Nie jestem pewien, czy to jest pomocne, ale to, co działało dla mnie w Rails 4
Foo.where.not(bar: nil)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 12:03:01