为Ruby模块中的每个方法调用执行代码

Gla*_*eep 37 ruby methods module metaprogramming

我正在Ruby 1.9.2中编写一个定义了几个方法的模块.当调用这些方法中的任何一个时,我希望它们中的每一个首先执行某个语句.

module MyModule
  def go_forth
    a re-used statement
    # code particular to this method follows ...
  end

  def and_multiply
    a re-used statement
    # then something completely different ...
  end
end
Run Code Online (Sandbox Code Playgroud)

但我想避免a re-used statement在每个方法中明确地放置该代码.有办法吗?

(如果重要的话,a re-used statement每个方法在调用时都会打印自己的名字.它会通过一些变体来实现puts __method__.)

hor*_*guy 66

像这样:

module M
  def self.before(*names)
    names.each do |name|
      m = instance_method(name)
      define_method(name) do |*args, &block|  
        yield
        m.bind(self).(*args, &block)
      end
    end
  end
end

module M
  def hello
    puts "yo"
  end

  def bye
    puts "bum"
  end

  before(*instance_methods) { puts "start" }
end

class C
  include M
end

C.new.bye #=> "start" "bum"
C.new.hello #=> "start" "yo"
Run Code Online (Sandbox Code Playgroud)

  • @ fl00r,所有你应该改变以使其在1.8.7中工作是proc调用语法,我使用`.()`(仅限1.9)而不是`.call()` (2认同)

Guo*_*Cao 11

这正是创建aspector的原因.

使用aspector,您无需编写样板元编程代码.您甚至可以更进一步将公共逻辑提取到单独的方面类中并独立测试.

require 'aspector'

module MyModule
  aspector do
    before :go_forth, :add_multiply do
      ...
    end
  end

  def go_forth
    # code particular to this method follows ...
  end

  def and_multiply
    # then something completely different ...
  end
end
Run Code Online (Sandbox Code Playgroud)