Is it possible to have a scope with optional arguments?

14,496

Solution 1

Yes. Just use a * like you would in a method.

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

Solution 2

Ruby 1.9 extended blocks to have the same features as methods do (default values are among them):

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

Call:

Model.cheap
Model.cheap(15)

Solution 3

I used scope :name, ->(arg1, arg2 = value) { ... } a few weeks ago, it worked well, if my memory's correct. To use with ruby 1.9+

Solution 4

You can conditionally modify your scope based on a given argument.

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

Usage:

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

Or, you can provide a default value.

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

Usage:

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

NOTE: The syntax shown for RANDOM() is specific to Postgres. The syntax shown is Rails 4.

Solution 5

Just wanted to let you know that according to the guide, the recommended way for passing arguments to scopes is to use a class method, like this:

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

This can give a cleaner approach.

Share:
14,496

Related videos on Youtube

tonymarschall
Author by

tonymarschall

Updated on June 11, 2022

Comments

  • tonymarschall
    tonymarschall almost 2 years

    Is it possible to write a scope with optional arguments so that i can call the scope with and without arguments?

    Something like:

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

    I can check in the lambda block if an arg is given (like described by Unixmonkey) but on calling the scope without an argument i got an ArgumentError: wrong number of arguments (0 for 1)

  • Paul Simpson
    Paul Simpson about 12 years
    Wouldn't you want to include a fallback for when no args are passed?
  • tonymarschall
    tonymarschall about 12 years
    I got an error if i do not pass an argument: ArgumentError: wrong number of arguments (0 for 1)
  • Christian
    Christian about 12 years
    You could use Proc.new instead of lambda to avoid the argument error. See this old discussion on this here