通过模块共享范围?

时间:2011-09-06 17:31:29

标签: ruby-on-rails activerecord rspec scope activemodel

我想通过将共享范围移动到模块中来干掉几个模型,例如:

module CommonScopes
  extend ActiveSupport::Concern

  module ClassMethods
    scope :ordered_for_display, order("#{self.to_s.tableize}.rank asc")
  end
end

我还想创建测试模块的共享规范。不幸的是,当我尝试在模型中包含共享范围时,我得到:

undefined method `order' for CommonScopes::ClassMethods:Module

有什么想法吗?谢谢!

3 个答案:

答案 0 :(得分:49)

与rails 4 scope syntax一样,您只需使用lambda来延迟代码的执行(也可以在rails 3中运行):

module CommonScopes
  extend ActiveSupport::Concern

  included do
    scope :ordered_for_display, -> { order("#{self.to_s.tableize}.rank asc") }
  end
end

答案 1 :(得分:13)

您可以使用instance_eval

module CommonScopes
  extend ActiveSupport::Concern

  def self.included(klass)
    klass.instance_eval do
      scope :ordered_for_display, order("#{self.to_s.tableize}.rank asc")
    end
  end
end

答案 2 :(得分:2)

因为当您的模块被Ruby解析时,会立即调用scope方法,并且无法从CommonScopes模块访问它。

但您可以通过类方法替换范围调用:

module CommonScopes
  extend ActiveSupport::Concern

  module ClassMethods
    def ordered_for_display
      order("#{self.to_s.tableize}.rank asc")
     end
  end
end