包装类方法的模块?
是否可以完成这项工作,而不必将模块包含在类的末尾,而只需将其包含在顶部?
module VerboseJob
def self.included(job_class)
class << job_class
alias_method :original_perform, :perform
def perform(*args)
JobLogger.verbose { original_perform(*args) }
end
end
end
end
class HelloJob
include VerboseJob
def self.perform(arg1, arg2)
puts "Job invoked with #{arg1} and #{arg2}"
end
end
我想要发生的是让 HelloJob.perform
实际调用 VerboseJob.perform
(然后调用块内的原始方法)。因为这里的模块包含在类的顶部,所以这不起作用,因为 perform
尚未定义。将 include
移到最后确实可行,但是有没有一种更宽容的方法?我喜欢将所有包含的模块保留在类定义的顶部。
我正在寻找一些在完全加载时在 Module
或 Class
上调用的方法,而不是由运行时解释的方法。
Is it possible to make this work, without having to include the module at the end of the class and just include it at the top?
module VerboseJob
def self.included(job_class)
class << job_class
alias_method :original_perform, :perform
def perform(*args)
JobLogger.verbose { original_perform(*args) }
end
end
end
end
class HelloJob
include VerboseJob
def self.perform(arg1, arg2)
puts "Job invoked with #{arg1} and #{arg2}"
end
end
What I want to happen, is for HelloJob.perform
to actually invoke VerboseJob.perform
(which then calls the original method inside a block). Because the module here is included at the top of the class, this doesn't work, since perform
isn't yet defined. Moving the include
to the end does work, but is there a way that's a bit more forgiving? I like to keep all the included modules at the top of my class definitions.
I'm sort of looking for some method that is called on Module
or Class
when it has been fully loaded, instead of as it is interpreted by the runtime.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是我想出的一种相当迂回/黑客的方法,将包装方法的定义推迟到原始方法被定义为止:
编辑:
d11wtq 将其简化为更清晰的:
Here is a rather roundabout/hackish way of doing it that I came up with by deferring the definition of the wrapper method until the original method had been defined:
Edit:
d11wtq simplified this to the much cleaner:
假设您希望在运行
perform
之前定义所有类,您可能需要使用 内核#at_exit:您可能还想了解单元测试框架(例如 Test::Unit 或 MiniTest)如何处理任务的延迟运行。
Assuming that you want all of your classes defined before you want
perform
run, you may want to use Kernel#at_exit:You may also want to look at how unit testing frameworks, such as Test::Unit or MiniTest, handle delaying the running of tasks.