Ruby:Open Module的单例

时间:2013-12-20 23:26:06

标签: ruby singleton

因此,在Ruby类中,您可以使用class << self之类的习惯用语,如下所示:

class SalesOrganization
  def self.find_new_leads
    ...
  end
  class << self
     include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
     add_transaction_tracer :find_new_leads, :category => :task
  end
end

我的问题是如果SalesOrganization实际上是Module而不是Class会怎样。这是在做我希望它会做什么,还是我开辟了一些我不应该涉足的黑魔法?

# Potentially terrible code
module SalesOrganization
      def self.find_new_leads
        ...
      end
      class << self
         include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
         add_transaction_tracer :find_new_leads, :category => :task
      end
end

如何访问模块单例类?

2 个答案:

答案 0 :(得分:3)

不,你没有发布任何黑魔法。您可以在任何对象上定义单例方法,包括模块(Module类的实例):

module M; end

def M.a
  "a"
end

M.a  # => "a"

你建议的方法也是如此:

module M
  def self.b
    "b"
  end
end

M.b  # => "b"

module M
  class << self
    def c
      "c"
    end
  end
end

M.c  # => "c"

如果在运行时之前不知道方法定义,也可以使用instance_eval

module M; end

M.instance_eval <<EOF
  def d
    "d"
  end
EOF

M.d  # => "d"

当然,像NewRelic...这样的模块可能会对它们所包含的类/模块做出假设,所以你必须要小心。

答案 1 :(得分:1)

我不确定我是否理解您要存档的内容。但是,如果您想在模块C中编写包含B的定义。而不是在C之后A使用B,而不是这样做:

module B
  def self.included(base)
    base.include C
  end
end

class A
  include B

  # use C
end

这是你的例子:

module SalesOrganization
  def self.included(base)
    base.include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
    base.add_transaction_tracer :find_new_leads, :category => :task
  end


  def self.find_new_leads
    ...
  end
end

如果您现在将SalesOrganization模块包含在类中,则该类将包含Newrelic内容。