Ruby on rails 通过模块共享作用域?

Ruby on rails 通过模块共享作用域?,ruby-on-rails,activerecord,rspec,scope,activemodel,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

我想通过将共享作用域移动到一个模块中来干涸几个模型,比如:

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

有什么想法吗?谢谢

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

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

module CommonScopes
  extend ActiveSupport::Concern

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

在rails 4中,您可以简单地使用lambda延迟代码的执行(在rails 3中也适用):


你不认为现在应该首选lambda吗?@mdemolin我认为在rails 4中不使用lambda调用
scope
是不可取的。正是我所说的:)(但我认为这只是目前首选的语法,还没有被否决)这也有点错误,因为它取消了扩展ActiveSupport::Concern的意义。作用域应位于块中,如
included do。。。结束
因为这是ActiveRecord::Concern的一部分,或者我们不应该费心扩展它,因为上面的
self.included
语法内置于每个Ruby模块中,与ActiveSupport::Concern无关。理想情况下,我们选择一种或另一种方式,因为ActiveSupport::Concern会处理我们在本答案示例中重新实现的样板代码。这适用于Rails 3和Rails 4,正如mdemolin的回答一样
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
module CommonScopes
  extend ActiveSupport::Concern

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