Ruby包含模块中模块的单一方法
我有一个以下模块
module SimpleTask def task1 end def task2 end def task3 end end
我有一个模型只需要模块SimpleTask
task2
方法。
我知道在我的模型中include SimpleTask
可以完成这项工作。
但我想知道我是否只能在我的模型中包含特定的task2
方法。
听起来你需要将#task2
重构为一个单独的模块(例如, BaseTask
)。 然后,您可以轻松地只包含BaseTask
,只需要#task2
。
module BaseTask def task2 ... end end module SimpleTask include BaseTask def task1 ... end def task3 ... end end
没有更具体的问题(例如SimpleTask
方法之间的相互依赖等),很难提供更多帮助。
您可以执行一些元编程,其中include SimpleTask
,然后include SimpleTask
定义您不想要的方法,但这是非常难看的IMO。
我要从delegate.rb中窃取一个例子,它限制了它包含的内容
... class Delegator < BasicObject kernel = ::Kernel.dup kernel.class_eval do [:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m| undef_method m end end include kernel ...
变
module PreciseInclude def include_except(mod, *except) the_module = mod.dup the_module.class_eval do except.each do |m| remove_method m # was undef_method, that prevents parent calls end end include the_module end end class Foo extend PreciseInclude include_except(SimpleTask, :task1, :task2) end Foo.instance_methods.grep(/task/) => [:task3]
你可以随时翻转它,而不是包含它成为include_only
问题是remove_method对嵌套模块不起作用,使用undef会阻止在整个层次结构中搜索该方法。
你可以添加
module SimpleTask def task1 end def task2 end def task3 end module_function :task2 end
因此,您可以像调用模块上的类方法一样调用该方法,并将其作为实例方法放在您想要所有三种方法的位置,即:
class Foo include SimpleTask end #=> Foo.new.task2 class LessFoo def only_needs_the_one_method SimpleTask.task2 end end #=> LessFoo.new.only_needs_the_one_method
或者,如果模块中确实没有共享状态,并且您不介意始终使用模块名称本身,则可以像这样声明所有方法类级别:
module SimpleTask def self.task1 end def self.task2 end def self.task3 end end class Foo include SimpleTask # Does, more or less nothing now def do_something SimpleTask.task1 end end #=> Foo.new.task2 #=> "task2 not a method or variable in Foo" #=> Foo.new.do_something does, however, work class LessFoo def only_needs_the_one_method SimpleTask.task2 end end #=> LessFoo.new.only_needs_the_one_method works as well in this case
但是在这种情况下你必须改变所有的呼叫者。
一个简单的解决方案是
define_method :task2, SimpleTask.instance_method(:task2)