Ruby模块中的动态覆盖类方法
Posted
技术标签:
【中文标题】Ruby模块中的动态覆盖类方法【英文标题】:Dynamic override class method in Ruby module 【发布时间】:2020-06-26 08:30:26 【问题描述】:是否可以在 Ruby 中动态覆盖类方法?
我有一个ErrorHandler
模块,它应该动态地创建一个具有给定名称的类方法,并执行与它覆盖的方法相同的操作:
module ErrorHandler
def self.handle_error_from(method_name)
define_singleton_method(method_name) do |*arguments|
begin
super(*arguments)
rescue
return "Handler return"
end
end
end
end
上面的模块是prepended
到另一个模块。
module AnotherModule
prepend ErrorHandler
ErrorHandler.handle_error_from :create
def self.create(params)
# Code here
end
end
上面的例子触发了ErrorHandler,但是并没有用创建的方法覆盖它。
我已经看到这是用实例方法完成的,但是当它是类方法时有限制吗?
【问题讨论】:
【参考方案1】:您的代码中有一些错误。
在您的模块中使用prepend
和self
,您实际上将在您的模块上定义包装方法。您可以尝试使用您的代码并在handle_error_from
之后添加puts ErrorHandler.methods
,您将看到它定义了create
方法。原因是本例中 self 是 ErrorHandler
。
你需要在定义原始方法之后再定义包装器方法。
在此处查看完整示例。
module ErrorHandler
def handle_error_from(method_name)
define_singleton_method(method_name) do |*arguments|
begin
super(*arguments)
rescue
puts "Handler return"
end
end
end
end
class Foo
extend ErrorHandler
def self.create
raise "error"
end
handle_error_from "create"
end
Foo.create
【讨论】:
上面的例子只是有点工作。由于某种原因,ErrorHandler 模块中的 super(*arguments) 总是抛出错误。知道这是为什么吗? 你能举个例子吗?请注意,我在create
方法中有 raise 'error'
以表明它正在工作。
这和你上面做的完全一样。但是它是通过 AWS Lambda 而不是 Foo.create 触发的。您认为设置会有所不同吗?以上是关于Ruby模块中的动态覆盖类方法的主要内容,如果未能解决你的问题,请参考以下文章