Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decorate a method in Ruby without alias_method_chain

We all know, that if the target class is composed with modules, you can just call super in a new module. But what if it is an ordinary method in a class?

class Logger
  def message(msg)
    puts msg
  end
end

Say, Logger is a class I can't change (e.g. it is in a gem). And I want Logger to put a "================" line before each message. How do I do that in a beauty way? Inheritance? Aggregation? How?

like image 694
Benedict Avatar asked Jan 21 '23 23:01

Benedict


1 Answers

You could save the original method as an unbound method object instead of saving it in an alias.

Then, you can use define_method with a block. The block will capture the unbound method_object in a closure, allowing you to use it in your new method, without having pollute your module/class.

The only downside is, you probably can't define a method that yields to or takes a block in this way:

module Mod
  unbound_method = instance_method(:original_method)
  define_method :original_method do |*args|
    #do something before
    #call the original method
    unbound_method.bind(self).call(*args)
    #do something after
  end
end
like image 164
PSkocik Avatar answered Jan 31 '23 01:01

PSkocik