我正在尝试创建一个类方法,该方法将超时包装器放在其他类方法周围。
class FooBar
def self.slow_add(a,b,c)
sleep 1
a + b + c
end
LIST = [:slow_add]
class << self
LIST.each do |x|
alias_method "#{x}_without_timeout", "#{x}"
define_method("#{x}_with_timeout") do |*args|
timeout(4){self.send(x, *args)}
end
alias_method "#{x}", "#{x}_with_timeout"
end
end
end
但是,生成的超时方法总是超时,即使它们不应该:
2.0.0p353 :152 > FooBar.slow_add_without_timeout(1, 2, 3)
=> 6
2.0.0p353 :153 > FooBar.slow_add_with_timeout(1, 2, 3)
Timeout::Error: execution expired
...
...
2.0.0p353 :156 > FooBar.slow_add(1, 2, 3)
Timeout::Error: execution expired
...
...
感谢您的帮助。
答案 0 :(得分:1)
如果您能够向您的班级发送超时消息非常重要,我建议您创建一个辅助类,它将在超时块中包装每个方法调用并将消息转发到原始类参考对象。像这样:
require 'timeout'
class TimeoutHandler
attr_reader :seconds, :object
def initialize(object, seconds)
@seconds = seconds
@object = object
end
def method_missing(name, *args, &block)
Timeout::timeout(seconds){ object.send(name, *args, &block) }
end
end
您可以像这样创建TimeoutHandler
的实例:
class FooBar
class << self
def timeout(seconds = 4)
TimeoutHandler.new(self, seconds)
end
end
end
因此,只要您需要使用超时块中断消息,您只需先在其上调用timeout
:
FooBar.timeout.slow_add(1, 2, 3)
您可以在mixin中编写timeout
方法,以包含在您需要此功能的类中。
但是,所有这一切对我来说都是非常有用的,我需要一个很好的理由来实现它,而不是仅仅使用更简单的Timeout::timeout { FooBar.slow_add(1, 2, 3) }
,它不需要任何额外的实现。< / p>