26

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

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

有任何想法吗?谢谢!

4

3 回答 3

65

与 rails 4范围语法一样,您可以简单地使用 lambda 来延迟代码的执行(也适用于 rails 3):

module CommonScopes
  extend ActiveSupport::Concern

  included do
    scope :ordered_for_display, -> { order("#{self.to_s.tableize}.rank asc") }
  end
end
于 2013-11-26T14:03:57.070 回答
17

您可以使用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
于 2011-09-06T17:54:31.703 回答
2

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

但是您可以用类方法替换您的范围调用:

module CommonScopes
  extend ActiveSupport::Concern

  module ClassMethods
    def ordered_for_display
      order("#{self.to_s.tableize}.rank asc")
     end
  end
end
于 2011-09-06T17:48:30.630 回答