Is there a hook similar to Class#inherited that's triggered only after a Ruby class definition? Is there a hook similar to Class#inherited that's triggered only after a Ruby class definition? ruby ruby

Is there a hook similar to Class#inherited that's triggered only after a Ruby class definition?


I am late, but I think I have an answer (to anyone who visit here).

You can trace until you find the end of the class definition. I did it in a method which I called after_inherited:

class Class  def after_inherited child = nil, &blk    line_class = nil    set_trace_func(lambda do |event, file, line, id, binding, classname|      unless line_class        # save the line of the inherited class entry        line_class = line if event == 'class'      else        # check the end of inherited class        if line == line_class && event == 'end'          # if so, turn off the trace and call the block          set_trace_func nil          blk.call child        end      end    end)  endend# testing...class A  def self.inherited(child)    after_inherited do      puts "XXX"    end  endendclass B < A  puts "YYY"  # .... code here can include class << self, etc.end

Output:

YYYXXX


You may be out of luck. But that's only a warning, not a definitive answer.

Ruby hooks the beginning of the class definition, rather than the end, for Class#inherited b/c ruby class definitions don't have a real end. They canbe reopened any time.

There was some talk a couple years ago about adding a const_added trigger, but it hasn't gone through yet. From Matz:

I'm not going to implement every possible hook. So when somebody comes with more concrete usage, I will consider this again. It would be const_added, not class_added.

So this might handle your case - but I'm not sure (it may trigger on the start too, when it's eventually implemented).

What are you trying to do with this trigger? There may be another way to do it.


Use TracePoint to track when your class sends up an :end event.

This module will let you create a self.finalize callback in any class.

module Finalize  def self.extended(obj)    TracePoint.trace(:end) do |t|      if obj == t.self        obj.finalize        t.disable      end    end  endend

Now you can extend your class and define self.finalize, which will run as soon as the class definition ends:

class Foo  puts "Top of class"  extend Finalize  def self.finalize    puts "Finalizing #{self}"  end  puts "Bottom of class"endputs "Outside class"# output:#   Top of class#   Bottom of class#   Finalizing Foo#   Outside class