Rails 3:如何编写 DRYer 作用域



我发现自己在两个地方编写非常相似的代码,一次是在模型上定义(虚拟)布尔属性,一次是定义范围以查找符合该条件的记录。基本上

scope :something, where(some_complex_conditions)
def something?
  some_complex_conditions
end

一个简单的例子:我正在模拟一个俱乐部会员资格;一个Member支付一个Fee,这只在某个year有效。

class Member < ActiveRecord::Base
  has_many :payments
  has_many :fees, :through => :payments
  scope :current, joins(:fees).merge(Fee.current)
  def current?
    fees.current.exists?
  end
end
class Fee < ActiveRecord::Base
  has_many :payments
  has_many :members, :through => :payments
  scope :current, where(:year => Time.now.year)
  def current?
    year == Time.now.year
  end
end

是否有一种 DRYer 方法来编写使用虚拟属性的范围(或者,确定模型是否与范围的条件匹配)?

我是 Rails 的新手,所以如果我在做一些愚蠢的事情,请指出!

这不是

问题的答案,但您的代码有一个错误(如果您在生产中使用类似的东西): Time.now.year 将返回服务器启动的年份。您希望在 lambda 中运行此作用域以使其按预期运行。

scope :current, lambda { where(:year => Time.now.year) }

不,没有更好的方法来做你想做的事情(除了注意Geraud的评论)。 在您的作用域中,您将定义一个类级过滤器,该过滤器将生成用于限制查找器返回的结果的 SQL,在属性中,您要定义要在此类的特定实例上运行的实例级测试。

是的,代码是相似的,但它在不同的上下文中执行不同的功能。

是的,您可以在作用域中使用一个或多个参数和 lambda。假设你有一组物品,并且您想取回那些"靴子"或"头盔"的物品:

  scope :item_type, lambda { |item_type|
    where("game_items.item_type = ?", item_type )
  } 

您现在可以game_item.item_type('Boot')只获取靴子,或者game_item.item_type('Helmet')只获取头盔。这同样适用于您的情况。您可以在作用域中只有一个参数,以便以 DRYer 方式检查同一作用域上的一个或多个条件。

相关内容

  • 没有找到相关文章

最新更新