【发布时间】:2011-01-15 11:34:49
【问题描述】:
假设有 3 个模型:A、B 和 C。每个模型都有 x 属性。
是否可以在模块中定义命名范围并将该模块包含在 A、B 和 C 中?
我尝试这样做并收到一条错误消息,指出无法识别scope...
【问题讨论】:
标签: ruby-on-rails ruby-on-rails-3 named-scope
假设有 3 个模型:A、B 和 C。每个模型都有 x 属性。
是否可以在模块中定义命名范围并将该模块包含在 A、B 和 C 中?
我尝试这样做并收到一条错误消息,指出无法识别scope...
【问题讨论】:
标签: ruby-on-rails ruby-on-rails-3 named-scope
是的
module Foo
def self.included(base)
base.class_eval do
scope :your_scope, lambda {}
end
end
end
【讨论】:
从 Rails 3.1 开始,ActiveSupport::Concern 稍微简化了语法:
现在你可以做
require 'active_support/concern'
module M
extend ActiveSupport::Concern
included do
scope :disabled, where(:disabled => true)
end
module ClassMethods
...
end
end
ActiveSupport::Concern 还扫描了所包含模块的依赖关系,here is the documentation
[更新,解决 aceofbassgreg 的评论]
Rails 3.1 和更高版本的 ActiveSupport::Concern 允许直接包含包含模块的实例方法,因此无需在包含的模块中创建 InstanceMethods 模块。此外,在 Rails 3.1 及更高版本中不再需要包含 M::InstanceMethods 和扩展 M::ClassMethods。所以我们可以有这样更简单的代码:
require 'active_support/concern'
module M
extend ActiveSupport::Concern
# foo will be an instance method when M is "include"'d in another class
def foo
"bar"
end
module ClassMethods
# the baz method will be included as a class method on any class that "include"s M
def baz
"qux"
end
end
end
class Test
# this is all that is required! It's a beautiful thing!
include M
end
Test.new.foo # ->"bar"
Test.baz # -> "qux"
【讨论】:
M::ClassMethods 并包含M::InstanceMethods,您需要将extend ActiveSupport::Concern 逻辑添加到M::InstanceMethods 模块中。也许在这种情况下,Les 在模型中包含了M(并且没有M::InstanceMethods 模块?)。
【讨论】: