我知道Ruby提供了一些有用的钩子方法。但是,我似乎找不到类似“constant_added
”钩子的东西。我想要的原因是因为我希望覆盖它,这样每当添加一个常量时,就更新一些变量执行某些其他操作而不必自己调用某种更新方法。
更具体地说,我试图保留一个与特定正则表达式匹配的所有现有常量的列表,但是没有循环遍历在特定时间间隔搜索匹配的所有现有常量,或者每当添加的最后一个常量与正则表达式匹配时更新列表;我相信这需要一个明确的方法调用。
如果某个钩子尚不存在,是否可以创建一个钩子,如果没有,我该怎样才能获得这种行为?
答案 0 :(得分:1)
我曾经使用Kernel.set_trace_func
在Ruby 1.9中做过。您可以继续检查"line"
个事件。每当发生此类事件时,使用constants
方法获取上一次常量的差异。如果您检测到差异,那么就是添加/删除常量的那一刻。
Kernel.set_trace_func ->event, _, _, _, _, _{
case event
when "line"
some_routine
end
}
Ruby 2.0可能有更强大的API,这允许更直接的方式来做到这一点,但我不确定。
答案 1 :(得分:0)
所以我想我已经提出了另一种选择:
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
我不是监视何时创建常量,而是在访问它时处理常量列表。所以现在我可以这样做:
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
你怎么看?这实现了我想要的东西,而且它相当简单,但我还是Ruby的新手,我不确定Ruby是否已经提供了一些很好的API来实现这一目标。