Executing code for every method call in a Ruby module

GladstoneKeep picture GladstoneKeep · Apr 1, 2011 · Viewed 23.4k times · Source

I'm writing a module in Ruby 1.9.2 that defines several methods. When any of these methods is called, I want each of them to execute a certain statement first.

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

But I want to avoid putting that a re-used statement code explicitly in every single method. Is there a way to do so?

(If it matters, a re-used statement will have each method, when called, print its own name. It will do so via some variant of puts __method__.)

Answer

horseyguy picture horseyguy · Apr 1, 2011

Like this:

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"