Does Ruby provide a constant_added hook method?

前端 未结 2 767
情歌与酒
情歌与酒 2021-01-22 07:15

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

相关标签:
2条回答
  • 2021-01-22 07:43

    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.

    0 讨论(0)
  • 2021-01-22 07:45

    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.

    0 讨论(0)
提交回复
热议问题