Подтвердить что ты не робот

Можно ли отменить область действия в Rails 3?

У меня есть следующий класс для моего класса с именем Collection:

scope :with_missing_coins, joins(:coins).where("coins.is_missing = ?", true)

Я могу запустить Collection.with_missing_coins.count и вернуть результат - он отлично работает! В настоящее время, если я хочу получать коллекции без пропущенных монет, я добавляю еще одну область:

scope :without_missing_coins, joins(:coins).where("coins.is_missing = ?", false)

Я нахожу, что пишу много этих "противоположных" областей. Можно ли получить противоположность области без ущерба для удобочитаемости или прибегнуть к лямбда/методу (который принимает true или false как параметр)?

Что-то вроде этого:

Collection.!with_missing_coins
4b9b3361

Ответ 1

Я бы не использовал для этого одну область, но два:

scope :with_missing_coins, joins(:coins).where("coins.is_missing = ?", true)
scope :without_missing_coins, joins(:coins).where("coins.is_missing = ?", false)

Таким образом, когда эти области используются, тогда он четко показывает, что происходит. С некоторыми числами1311407, не сразу понятно, что делает аргумент false для with_missing_coins.

Мы должны попытаться написать код как можно яснее, и если это означает, что он менее ревнив о DRY один раз в то время, как и так.

Ответ 2

В Rails 4.2 вы можете:

scope :original, -> { ... original scope definition ... }
scope :not_original, -> { where.not(id: original) }

Он будет использовать подзапрос.

Ответ 3

Там нет "разворота" объема как такового, хотя я не думаю, что прибегать к методу лямбда - проблема.

scope :missing_coins, lambda {|status| 
  joins(:coins).where("coins.is_missing = ?", status) 
}

# you could still implement your other scopes, but using the first
scope :with_missing_coins,    lambda { missing_coins(true) }
scope :without_missing_coins, lambda { missing_coins(false) }

то

Collection.with_missing_coins
Collection.without_missing_coins

Ответ 4

это могло бы просто работать, не проверял это много. использует rails 5 Я думаю, что rails 3 имеет метод where_values вместо where_clause.

        scope :not, ->(scope_name) { query = self
      send(scope_name).joins_values.each do |join|
      query = query.joins(join)
    end
                                    query.where((send(scope_name).where_clause.send(:predicates).reduce(:and).not))}

использование

Model.not(: SCOPE_NAME)

Ответ 5

Обновите. Теперь в Rails 6 добавлены удобные и изящные методы с отрицательным перечислением.

# All inactive devices
# Before
Device.where.not(status: :active)
#After 
Device.not_active

сообщение в блоге здесь