How do I wrap the invocation of a Ruby method by including a module?

前端 未结 3 1227
暖寄归人
暖寄归人 2020-12-29 13:52

I want to be notified when certain things happen in some of my classes. I want to set this up in such a way that the implementation of my methods in those classes doesn\'t c

3条回答
  •  攒了一身酷
    2020-12-29 14:30

    It has been quite a while since this question here has been active, but there is another possibility to wrap methods by an included (or extended) Module.

    Since 2.0 you can prepend a Module, effectively making it a proxy for the prepending class.

    In the example below, a method of an extended module module is called, passing the names of the methods you want to be wrapped. For each of the method names, a new Module is created and prepended. This is for code simplicity. You can also append multiple methods to a single proxy.

    An important difference to the solutions using alias_method and instance_method which is later bound on self is that you can define the methods to be wrapped before the methods themselves are defined.

    module Prepender
    
      def wrap_me(*method_names)
        method_names.each do |m|
          proxy = Module.new do
            define_method(m) do |*args|
              puts "the method '#{m}' is about to be called"
              super *args
            end
          end
          self.prepend proxy
        end
      end
    end
    

    Use:

    class Dogbert
      extend Prepender
    
      wrap_me :bark, :deny
    
      def bark
        puts 'Bah!'
      end
    
      def deny
        puts 'You have no proof!'
      end
    end
    
    Dogbert.new.deny
    
    # => the method 'deny' is about to be called
    # => You have no proof!
    

提交回复
热议问题