使用NoMethodError处理程序而不是method_missing进行动态方法调用

时间:2010-01-27 06:54:38

标签: ruby metaprogramming

我正在尝试为动态重新加载过程制作API;现在我想要在所有上下文中提供一个名为reload!的方法,但是,我正在一个具有某种状态的对象上实现此方法(因此它不能在内核上)

假设我们有像

这样的东西
WorkerForker.run_in_worker do
  # some code over here...
  reload! if some_condition
end

run_in_worker方法中,有如下代码:

begin
  worker = Worker.new(pid, stream)
  block.call
rescue NoMethodError => e
  if (e.message =~ /reload!/) 
    puts "reload! was called"
    worker.reload! 
  else
    raise e
  end
end

所以我这样做是因为我想在任何嵌套的上下文中使reload!方法可用,而且我不想弄乱我在instance_eval上收到的块worker实例。

所以我的问题是,这种方法有任何复杂性吗?我不知道是否有人已经这样做了(还没有读过那么多代码),如果它已经完成了?有没有更好的方法来实现此代码的目标?

3 个答案:

答案 0 :(得分:1)

假设我现在了解你,那怎么样:

my_object = Blah.new
Object.send(:define_method, :reload!) { 
    my_object.reload!
    ...
}

使用此方法调用reload!方法的每个对象都会修改相同的共享状态,因为传递给my_object的块会捕获define_method

答案 1 :(得分:0)

这样做有什么问题?

def run_in_worker(&block)
    ...
    worker = Worker.new(pid, stream)
    block.call(worker)
end

WorkerForker.run_in_worker do |worker|
    worker.reload! if some_condition
end

答案 2 :(得分:0)

听起来你只是希望每个方法都知道一个对象而没有方法或方法的所有者被告知它。实现这一目标的方法是全局变量。它通常不被认为是一个好主意(因为它会导致并发问题,所有权问题,使单元测试变得更加困难等),但如果这就是你想要的,那就是它。