mkkl
mkkl

Reputation: 263

Dynamic override class method in Ruby module

Is it possible to dynamically override a class method in Ruby?

I have a ErrorHandler module which should dynamically create a class method with a given name and do the same as the method it is overriding:

module ErrorHandler
    def self.handle_error_from(method_name)
      define_singleton_method(method_name) do |*arguments|
        begin
          super(*arguments)
        rescue
          return "Handler return"
        end
      end
    end
  end

The above module is prepended to another module.

module AnotherModule
      prepend ErrorHandler

      ErrorHandler.handle_error_from :create

      def self.create(params)
       # Code here
      end
end

The above example triggers the ErrorHandler but it does not override it with the created method.

I've seen this be done with instance methods, but is there a limitation when it is class methods?

Upvotes: 1

Views: 614

Answers (1)

Christian Bruckmayer
Christian Bruckmayer

Reputation: 2187

You have a few errors in your code.

  1. With prepend and self in your module you will actually define the wrapper method on your module. You can try this with using your code and add a puts ErrorHandler.methods after the handle_error_from and you will see it has a create method defined. The reason is that self is ErrorHandler in this case.

  2. You need to define the wrapper method after the original method is defined.

See here a full example.

module ErrorHandler
    def handle_error_from(method_name)
      define_singleton_method(method_name) do |*arguments|
        begin
          super(*arguments)
        rescue
          puts  "Handler return"
        end
      end
    end
end


class Foo
  extend ErrorHandler

  def self.create
    raise "error"
  end
  handle_error_from "create"
end

Foo.create

Upvotes: 1

Related Questions