是否可以有一个带有可选参数的范围?

Posted

技术标签:

【中文标题】是否可以有一个带有可选参数的范围?【英文标题】:Is it possible to have a scope with optional arguments? 【发布时间】:2012-05-07 11:47:27 【问题描述】:

是否可以编写一个带有可选参数的作用域,以便我可以调用带参数和不带参数的作用域?

类似:

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


Model.with_optional_args('foo')
Model.with_optional_args

如果给定了 arg(如 Unixmonkey 所述),我可以检查 lambda 块,但是在没有参数的情况下调用范围时,我得到了 ArgumentError: wrong number of arguments (0 for 1)

【问题讨论】:

【参考方案1】:

几周前我使用了scope :name, ->(arg1, arg2 = value) ... ,如果我没记错的话,它运行良好。与 ruby​​ 1.9+ 一起使用

【讨论】:

【参考方案2】:

使用 *

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

【讨论】:

【参考方案3】:

您可以根据给定的参数有条件地修改您的范围。

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。

【讨论】:

【参考方案4】:

当然。

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

【讨论】:

你不想在没有参数传递时包含一个后备吗? 如果我不传递参数,我得到一个错误:ArgumentError: wrong number of arguments (0 for 1) 您可以使用 Proc.new 而不是 lambda 来避免参数错误。请参阅有关此 here 的旧讨论【参考方案5】:

只是想让您知道,根据guide,将参数传递给作用域的推荐方法是使用类方法,如下所示:

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

这可以提供更简洁的方法。

【讨论】:

【参考方案6】:

Ruby 1.9 扩展块具有与方法相同的功能(其中包含默认值):

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

呼叫:

Model.cheap
Model.cheap(15)

【讨论】:

【参考方案7】:

是的。只需像在方法中一样使用*

scope :print_args, lambda |*args|
    puts args

【讨论】:

以上是关于是否可以有一个带有可选参数的范围?的主要内容,如果未能解决你的问题,请参考以下文章

可选输出光标作为参数

带有可选参数的 MVC 操作——哪个更好?

带有可选“WHERE”参数的存储过程

带有可选参数的 JpaRepository

带有可选第一路由参数的Vue路由器路由

Go/可选参数中的多个构造函数?