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

r00*_*00k 3 ruby ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)

然后我extend ExpiresWithinScope在我的模型中做.

这种方法有效,但感觉有点hackish.有没有更好的办法?

Bar*_*cat 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
Run Code Online (Sandbox Code Playgroud)

然后在你的模型中

include ExpiresWithinScope
Run Code Online (Sandbox Code Playgroud)

  • 这是有效的,除了你需要`base.where`. (4认同)

Rea*_*onk 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
Run Code Online (Sandbox Code Playgroud)

你也可以尝试:

module ExpiresWithinScope
  def expires_within(months_from_now)
    where(:expiration_date => Date.today..(Date.today + number_of_months_from_now))
  end
end
Run Code Online (Sandbox Code Playgroud)

但根据指南,arel也无法处理.