Jeśli mam zasięg z lambda i wymaga on argumentu, w zależności od wartości argumentu, mógłbym wiedzieć, że nie będzie żadnych dopasowań, ale nadal chcę zwrócić relację, a nie pustą tablicę:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
To, czego tak naprawdę chcę, to metoda „none”, przeciwieństwo „all”, która zwraca relację, która może być nadal powiązana, ale powoduje zwarcie zapytania.
ruby-on-rails
activerecord
relation
dzajic
źródło
źródło
Odpowiedzi:
W Railsach 4 jest teraz „poprawny” mechanizm:
źródło
Model.scoped
robi to, czego szukasz w szynach 3.Model.none
nie działa. Musisz użyć jednej ze swoich prawdziwych nazw modeli, np.User.none
Lub co masz.Bardziej przenośne rozwiązanie, które nie wymaga kolumny „id” i nie zakłada, że nie będzie wiersza o identyfikatorze 0:
Nadal szukam bardziej „poprawnego” sposobu.
źródło
scope :none, -> { where("false") }
Jadąc w szynach 4
W Railsach 4 łańcuch
ActiveRecord::NullRelation
będzie zwracany z takich połączeńPost.none
.Ani to, ani powiązane metody nie będą generować zapytań do bazy danych.
Zgodnie z komentarzami:
Zobacz kod źródłowy .
źródło
Możesz dodać zakres o nazwie „none”:
To da ci pusty ActiveRecord :: Relacja
Możesz także dodać go do ActiveRecord :: Base w inicjalizatorze (jeśli chcesz):
Wiele sposobów na uzyskanie czegoś takiego, ale na pewno nie najlepsza rzecz do przechowywania w bazie kodu. Użyłem zakresu: brak podczas refaktoryzacji i stwierdzenia, że muszę zagwarantować pusty ActiveRecord :: Relacja przez krótki czas.
źródło
where('1=2')
może być nieco bardziej zwięzłyModel.none
jak to zrobić.Jest to niebezpieczne rozwiązanie, ponieważ Twój zasięg może być związany.
User.none.first
zwróci pierwszego użytkownika. Jest bezpieczniejszy w użyciu
źródło
Myślę, że wolę sposób, w jaki to wygląda od innych opcji:
Prowadząc do czegoś takiego:
źródło
where(false)
nie miałby wykonywać tej pracy - pozostawia zakres bez zmian.limit(0)
zostanie zastąpione, jeśli zadzwonisz.first
lub.last
później w łańcuchu, ponieważ Railsy dołącząLIMIT 1
do tego zapytania.none
relację, jak wspomniano poniżej.Użyj zakresu:
Ale możesz także uprościć swój kod za pomocą:
Jeśli chcesz uzyskać pusty wynik, użyj tego (usuń warunek if):
źródło
Jest to możliwe, a więc to:
http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none
Popraw mnie, jeśli się mylę.
źródło
Istnieją również warianty, ale wszystkie one przesyłają żądanie do db
źródło
where(false)
lubwhere(nil)
jest po prostu ignorowany.