2012-04-26 12 views
14

¿Es posible escribir un alcance con argumentos opcionales para que pueda llamar al alcance con y sin argumentos?¿Es posible tener un alcance con argumentos opcionales?

Algo así como:

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

Model.with_optional_args('foo') 
Model.with_optional_args 

puedo comprobar en el bloque lambda si se da una Arg (como se describe por Unixmonkey) pero en llamar el alcance y sin un argumento Tengo una ArgumentError: wrong number of arguments (0 for 1)

Respuesta

18

Sí. Simplemente use un * como lo haría en un método.

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

Ciertamente.

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

no usted desee incluir una reserva para cuando no se pasan argumentos? –

+0

Obtuve un error si no paso un argumento: ArgumentError: número de argumentos incorrectos (0 para 1) – tonymarschall

+2

Puede usar Proc.new en lugar de lambda para evitar el error del argumento. Vea este viejo debate sobre esto [aquí] (https://rails.lighthouseapp.com/projects/8994/tickets/90-enhancement-add-support-for-named-scopes-with-optional-arguments) – Christian

8

que utilizan scope :name, ->(arg1, arg2 = value) { ... } hace unas semanas, funcionó bien, si es correcto memoria. Para usar con ruby ​​1.9+

20

Ruby 1.9 bloques extendidos tengan las mismas características que los métodos de hacer (valores predeterminados están entre ellos):

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

Llamar:

Model.cheap 
Model.cheap(15) 
3

Sólo quería hacerle saber que de acuerdo con guide, la forma recomendada para pasar argumentos a ámbitos es usar un método de clase, como este:

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

Esto puede proporcionar un enfoque más limpio.

5

Puede modificar su alcance de forma condicional en función de un argumento determinado.

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

Uso:

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

O bien, puede proporcionar un valor por defecto.

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

Uso:

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

NOTA: La sintaxis mostrada por RANDOM() es específico de Postgres. La sintaxis que se muestra es Rieles 4.

0

Uso del *

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