背景:

我有一个模块,它声明了许多实例方法

module UsefulThings
  def get_file; ...
  def delete_file; ...

  def format_text(x); ...
end

我想在类中调用其中一些方法。在ruby中你通常是这样做的:

class UsefulWorker
  include UsefulThings

  def do_work
    format_text("abc")
    ...
  end
end

问题

include UsefulThings引入了UsefulThings中的所有方法。在这种情况下,我只需要format_text和显式不需要get_file和delete_file。

我可以看到几个可能的解决方案:

Somehow invoke the method directly on the module without including it anywhere I don't know how/if this can be done. (Hence this question) Somehow include Usefulthings and only bring in some of it's methods I also don't know how/if this can be done Create a proxy class, include UsefulThings in that, then delegate format_text to that proxy instance This would work, but anonymous proxy classes are a hack. Yuck. Split up the module into 2 or more smaller modules This would also work, and is probably the best solution I can think of, but I'd prefer to avoid it as I'd end up with a proliferation of dozens and dozens of modules - managing this would be burdensome

为什么一个模块中有很多不相关的功能?它是来自rails应用程序的ApplicationHelper,我们的团队实际上已经决定将它作为任何不够特定而不属于其他任何地方的东西的垃圾场。大多数是独立的实用程序方法,在任何地方都可以使用。我可以把它分解成独立的助手,但有30个,每个都有一个方法……这似乎没有什么效果


当前回答

a .如果你总是想以一种“限定的”独立的方式调用它们(UsefulThings.get_file),那么就像其他人指出的那样,让它们成为静态的,

module UsefulThings
  def self.get_file; ...
  def self.delete_file; ...

  def self.format_text(x); ...

  # Or.. make all of the "static"
  class << self
     def write_file; ...
     def commit_file; ...
  end

end

B.如果你仍然想在相同的情况下保持mixin方法,以及一次性的独立调用,你可以有一个单行模块,用mixin扩展自己:

module UsefulThingsMixin
  def get_file; ...
  def delete_file; ...

  def format_text(x); ...
end

module UsefulThings
  extend UsefulThingsMixin
end

所以两者都适用:

  UsefulThings.get_file()       # one off

   class MyUser
      include UsefulThingsMixin  
      def f
         format_text             # all useful things available directly
      end
   end 

恕我直言,对于每一个单独的方法,它都比module_function更干净——以防需要所有的方法。

其他回答

我认为丢弃单个调用(不改变现有模块或创建新模块)的最短方法如下:

Class.new.extend(UsefulThings).get_file

调用模块实例方法时不包含模块(也不创建中间对象):

class UsefulWorker
  def do_work
    UsefulThings.instance_method(:format_text).bind(self).call("abc")
    ...
  end
end

如果你想调用这些方法而不将module包含在另一个类中,那么你需要将它们定义为模块方法:

module UsefulThings
  def self.get_file; ...
  def self.delete_file; ...

  def self.format_text(x); ...
end

然后你就可以打电话给他们

UsefulThings.format_text("xxx")

or

UsefulThings::format_text("xxx")

但无论如何,我建议你把相关的方法放在一个模块或一个类中。如果你只想从模块中包含一个方法,那么这听起来就像是一种糟糕的代码味道,将不相关的方法放在一起不是好的Ruby风格。

不确定10年后是否有人还需要它,但我用特征类解决了它。

module UsefulThings
  def useful_thing_1
    "thing_1"
  end

  class << self
    include UsefulThings
  end
end

class A
  include UsefulThings
end

class B
  extend UsefulThings
end

UsefulThings.useful_thing_1 # => "thing_1"
A.new.useful_thing_1 # => "thing_1"
B.useful_thing_1 # => "thing_1"

a .如果你总是想以一种“限定的”独立的方式调用它们(UsefulThings.get_file),那么就像其他人指出的那样,让它们成为静态的,

module UsefulThings
  def self.get_file; ...
  def self.delete_file; ...

  def self.format_text(x); ...

  # Or.. make all of the "static"
  class << self
     def write_file; ...
     def commit_file; ...
  end

end

B.如果你仍然想在相同的情况下保持mixin方法,以及一次性的独立调用,你可以有一个单行模块,用mixin扩展自己:

module UsefulThingsMixin
  def get_file; ...
  def delete_file; ...

  def format_text(x); ...
end

module UsefulThings
  extend UsefulThingsMixin
end

所以两者都适用:

  UsefulThings.get_file()       # one off

   class MyUser
      include UsefulThingsMixin  
      def f
         format_text             # all useful things available directly
      end
   end 

恕我直言,对于每一个单独的方法,它都比module_function更干净——以防需要所有的方法。