I know that there are several useful hook methods that Ruby provides. However, I couldn\'t seem to find anything like a \'constant_added
\' hook. The reason I would
I once did it in Ruby 1.9 using Kernel.set_trace_func
. You can keep checking for "line"
events. Whenever such event occurs, take the difference of the constants from the previous time using the constants
method. If you detect a difference, then that is the moment a constant was added/removed.
Kernel.set_trace_func ->event, _, _, _, _, _{
case event
when "line"
some_routine
end
}
Ruby 2.0 may have more powerful API, which allows for a more straightforward way to do it, but I am not sure.
So I think I've come up with an alternative:
class Object
def typedef &block
Module.new &block
end
end
module Type
@@types = []
@@prev = Module.constants
def self.existing_types
diff = Module.constants - @@prev
@@prev = Module.constants
new_types = diff.select { |const| const.to_s.start_with? 'TYPE_' }
@@types |= new_types
end
end
Instead of monitoring when constants are created, I process the constant list when I access it. So now I can do something like this:
irb(main):002:0> Type.existing_types
=> []
irb(main):003:0> TYPE_rock = typedef do
irb(main):004:1* def self.crumble
irb(main):005:2> puts "I'm crumbling! D:"
irb(main):006:2> end
irb(main):007:1> end
=> TYPE_rock
irb(main):008:0> Type.existing_types
=> [:TYPE_rock]
irb(main):009:0> FOO_CONST = 54
=> 54
irb(main):011:0> TYPE_water = typedef do
irb(main):012:1* def self.splash
irb(main):013:2> puts "Water! :3"
irb(main):014:2> end
irb(main):015:1> end
=> TYPE_water
irb(main):016:0> Type.existing_types
=> [:TYPE_rock, :TYPE_water]
irb(main):017:0> TYPE_rock.crumble
I'm crumbling! D:
=> nil
irb(main):018:0> TYPE_water.splash
Water! :3
=> nil
What do you think? This accomplishes what I want, and it's fairly simple but I'm still new to Ruby and I'm not sure if there's some nice API that Ruby might already provide to do this.