模块同时扩展和包含?

时间:2013-11-24 21:57:58

标签: ruby dsl

我正在扩展一个类来接受DSL。实例应始终使用默认值进行响应,但代码可能会更改。当我调用设置who_am_i方法的i_am时,下面的代码工作正常,但我无法弄清楚如何设置默认方法。

module Helper
  def i_am
    "Default code"
  end
  def who_am_i
    class_eval(<<-EOS, __FILE__, __LINE__ + 1)
      def i_am
        "This was executed in class: \#{self.class.to_s}"
      end
  EOS
  end
end

class Test
  extend Helper
end

t = Test.new
t.i_am

我可以通过这样做来完成这项工作:

class Test2
  extend Helper
  include Helper
end

t2 = Test2.new
t2.i_am

但这看起来很怪异。想法?

2 个答案:

答案 0 :(得分:3)

您需要使用包含的方法/钩子。每当给定模块包含在其他类或模块中时,它就会被运行,这个类或模块用于参数。在你的情况下你想要:

module Helper
  def i_am
    "Default code"
  end

  def self.included mod
    mod.extend ClassMethods
  end

  module ClassMethods
    def who_am_i
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def i_am
          "This was executed in class: \#{self.class.to_s}"
        end
    EOS
    end
  end
end

class Tester
  include Helper
end

答案 1 :(得分:1)

啊哈!

答案是使用module.included()使其扩展类。这样你就可以使用“include Helper”了 “include”部分将调用“Helper.included”并传递给调用者,并使用它来扩展它!

参考:http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/

module Helper

  def i_am
    "Default code"
  end

  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def who_am_i
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def i_am
          "This was executed in class: \#{self.class.to_s}"
        end
  EOS
    end
  end
end


class Test
  include Helper
end