Как вернуть пустое отношение ActiveRecord?
Если у меня есть область с лямбда и она принимает аргумент, в зависимости от значения аргумента, я могу знать, что не будет никаких совпадений, но я все равно хочу вернуть отношение, а не пустой массив:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
то, что я действительно хочу,-это метод "none", противоположный "all", который возвращает отношение, которое все еще может быть связано, но приводит к короткому замыканию запроса.
9 ответов:
более портативное решение, которое не требует столбца " id " и не предполагает, что не будет строки с идентификатором 0:
scope :none, where("1 = 0")
Я все еще ищу более "правильный" путь.
вы можете добавить область под названием "Нет":
scope :none, where(:id => nil).where("id IS NOT ?", nil)
это даст вам пустой ActiveRecord:: Relation
вы также можете добавить его в ActiveRecord::Base в инициализаторе (если хотите):
class ActiveRecord::Base def self.none where(arel_table[:id].eq(nil).and(arel_table[:id].not_eq(nil))) end end
много способов получить что-то вроде этого, но, конечно, не лучшая вещь, чтобы держать в базе кода. Я использовал scope: none при рефакторинге и обнаружил, что мне нужно гарантировать пустое отношение ActiveRecord:: в течение короткого времени.
идешь в Rails 4
в рельсах 4, цепной
ActiveRecord::NullRelation
будет возвращен из вызовов, какPost.none
.ни он, ни цепные методы не будут генерировать запросы к базе данных.
в соответствии с комментариями:
возвращенная ActiveRecord:: NullRelation наследует от Связь и реализует шаблон нулевого объекта. Это объект с определенное поведение null и всегда возвращает пустой массив записей без quering база данных.
посмотреть исходный код.
scope :none, limit(0)
это опасное решение, потому что ваш объем может быть прикован.
пользователей.никто.первый
вернет первого пользователя. Это безопаснее использовать
scope :none, where('1 = 0')
Я думаю, что я предпочитаю, как это выглядит для других вариантов:
scope :none, limit(0)
приведет к чему-то вроде этого:
scope :users, lambda { |ids| ids.present? ? where("user_id IN (?)", ids) : limit(0) }
используйте scoped:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : scoped }но, вы также можете упростить ваш код:
scope :for_users, lambda { |users| where(:user_id => users.map(&:id)) if users.any? }Если вы хотите пустой результат, используйте эту (убрать условие if):
scope :for_users, lambda { |users| where(:user_id => users.map(&:id)) }
можно и так вот:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : User.none }
http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none
поправьте меня, если я ошибаюсь.