Search code examples
ruby

Running a method after the initialize method


I would like to write some ruby code that runs after the initialize method is called. This code can be in a class or a module. How would I write this?

Here is an example of what I want:

class Base
  def after_init
    puts "after init"
  end

class A < Base # Option 1, use a class
end

class B < Base
  def initialize
    puts "in init"
  end
end

module MyMod
  def after_init
    puts "after init"
  end
end

class C
  include Module
end

$> A.new
=> "after init"
$> B.new
=> "in init"
=> "after init"
$> C.new
=> "after init"

What I definitely don't want to do is make an explicit call to super. Is there a way to do this? I don't care if it uses a lot of Ruby's reflective abilities. Thanks!


Solution

  • class Base
      def after_init
        puts "Base#after_init"
      end
    
      def self.inherited(klass)
        class << klass
          alias_method :__new, :new
          def new(*args, **args)
            e = __new(*args, **args)
            e.after_init
            e
          end
        end
      end
    end
    
    module MyMod
      def after_init
        puts "MyMod#after_init"
      end
      def self.included(klass)
        class << klass
          alias_method :__new, :new
          def new(*args, **args)
            e = __new(*args, **args)
            e.after_init
            e
          end
        end
      end
    end
    
    class A < Base
    end
    
    class B < Base
      def initialize
        puts "B#initialize"
      end
    end
    
    class C
      include MyMod
      def initialize
        puts "C#initialize"
      end
    end
    
    A.new
    B.new
    C.new