Ruby包含模块中模块的单一方法

Gag*_*gan 14 ruby methods module include

我有一个以下的模块

module SimpleTask
    def task1
    end
    def task2
    end
    def task3
    end
end
Run Code Online (Sandbox Code Playgroud)

我有一个只需要task2模块方法的模型SimpleTask.

我知道包括SimpleTask在我的模型中include SimpleTask可以完成这项工作.

但我想知道我是否只能task2在我的模型中包含特定方法.

kro*_*ugh 7

听起来你需要重构成#task2一个单独的模块(例如BaseTask).然后,您可以轻松地只包含BaseTask您需要的地方#task2.

module BaseTask
  def task2
    ...
  end
end

module SimpleTask
  include BaseTask

  def task1
    ...
  end

  def task3
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)

没有更具体的问题(例如方法之间的相互依赖等),很难提供更多的帮助SimpleTask.

可以在那里进行一些元编程,include SimpleTask然后取消定义你不想要的方法,但这是非常难看的IMO.

  • 这个问题没有什么问题,问得很好,也很清楚。我进入此页面是因为我有完全相同的问题。我不想创建新模块,也不想在类命名空间中包含不必要的其他方法。我只想包含模块中的一个方法。 (2认同)

Tim*_*ite 6

你可以添加

module SimpleTask
    def task1
    end
    def task2
    end
    def task3
    end
    module_function :task2
end
Run Code Online (Sandbox Code Playgroud)

所以,你可以调用像模块上的类方法的方法以及具有其作为地方的实例方法你做到想所有这三种方法,即:

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
Run Code Online (Sandbox Code Playgroud)

或者,如果模块中确实没有共享状态,并且您不介意始终使用模块名称本身,则可以像这样声明所有方法类级别:

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
Run Code Online (Sandbox Code Playgroud)

但在这种情况下你必须改变所有的呼叫者.


jtz*_*ero 6

我将从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
...
Run Code Online (Sandbox Code Playgroud)

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]
Run Code Online (Sandbox Code Playgroud)

你可以随时翻转它而不是包含它 include_only

问题是remove_method对嵌套模块不起作用,使用undef会阻止在整个层次结构中搜索该方法.