Возможно ли иметь область с необязательными аргументами?

Можно ли написать область с необязательными аргументами, чтобы я мог вызывать область с аргументами и без них?

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

scope :with_optional_args,  lambda { |arg|
  where("table.name = ?", arg)
}

Model.with_optional_args('foo')
Model.with_optional_args

Я могу проверить блок лямбда, если задан аргумент arg (как описано Unixmonkey), но при вызове области без аргумента я получил ArgumentError: wrong number of arguments (0 for 1)

Ответы

Ответ 1

Да. Просто используйте *, как в методе.

scope :print_args, lambda {|*args|
    puts args
}

Ответ 2

Расширенные блоки Ruby 1.9 имеют те же функции, что и методы (значения по умолчанию среди них):

scope :cheap, lambda{|max_price=20.0| where("price < ?", max_price)}

Вызов:

Model.cheap
Model.cheap(15)

Ответ 3

Я использовал scope :name, ->(arg1, arg2 = value) { ... } несколько недель назад, он работал хорошо, если память правильная. Для использования с ruby ​​1.9 +

Ответ 4

Вы можете условно изменить свою область действия на основе заданного аргумента.

scope :random, ->(num = nil){ num ? order('RANDOM()').limit(num) : order('RANDOM()') }

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

Advertisement.random # => returns all records randomized
Advertisement.random(1) # => returns 1 random record

Или вы можете указать значение по умолчанию.

scope :random, ->(num = 1000){ order('RANDOM()').limit(num) }

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

Product.random # => returns 1,000 random products
Product.random(5) # => returns 5 random products

ПРИМЕЧАНИЕ. Синтаксис, показанный для RANDOM(), специфичен для Postgres. Синтаксис показан Rails 4.

Ответ 5

Просто хотел сообщить вам, что в соответствии с guide рекомендуемым способом передачи аргументов в области видимости является использование метода класса, вот так:

class Post < ActiveRecord::Base
  def self.1_week_before(time)
    where("created_at < ?", time)
  end
end

Это может дать более чистый подход.

Ответ 6

Конечно.

scope :with_optional_args,  Proc.new { |arg|
  if arg.present?
    where("table.name = ?", arg)
  end
}

Ответ 7

Используйте *

scope :with_optional_args,  -> { |*arg| where("table.name = ?", arg) }