在Rails 3中定义模块内部范围的最佳方法是什么?

时间:2010-09-16 18:09:05

标签: ruby-on-rails ruby ruby-on-rails-3

我有许多需要相同范围的模型。它们每个都有一个expiration_date日期字段,我想写一个范围。

为了保持DRY,我想将范围放在一个模块(在/ lib中)中,我将扩展每个模型。但是,当我在模块中调用scope时,该方法是未定义的。

要解决此问题,我在使用模块时使用class_eval

module ExpiresWithinScope
  def self.extended(base)
    scope_code = %q{scope :expires_within, lambda { |number_of_months_from_now| where("expiration_date BETWEEN ? AND ?", Date.today, Date.today + number_of_months_from_now) } }
    base.class_eval(scope_code)
  end 
end

然后我在模特中做extend ExpiresWithinScope

这种方法有效,但感觉有点hackish。还有更好的方法吗?

2 个答案:

答案 0 :(得分:10)

你可以做一些像这样的清洁工作,因为范围是公共类方法:

module ExpiresWithinScope
  def self.included(base)
    base.scope :expires_within, lambda { |number_of_months_from_now| 
      base.where("expiration_date BETWEEN ? AND ?", 
        Date.today,
        Date.today + number_of_months_from_now) 
    }
  end 
end

然后在你的模型中

include ExpiresWithinScope

答案 1 :(得分:5)

使用AR3,他们终于在DataMapper附近获得了很棒的地方,所以你可以去

module ExpiresWithinScope
  def expires_within(months_from_now)
    where("expiration_date BETWEEN ? AND ?", 
    Date.today,
    Date.today + number_of_months_from_now) 
  end
end

您也可以尝试:

module ExpiresWithinScope
  def expires_within(months_from_now)
    where(:expiration_date => Date.today..(Date.today + number_of_months_from_now))
  end
end

但根据the guide,arel也无法解决这个问题。