Ruby使用prepend修补类不';行不通
我正在尝试修补sinatra中的动词方法,以便在其之前添加额外的函数调用。我在使用别名链来保留原始方法时遇到了问题,但我发现prepend允许我在不使用这种黑客方法的情况下做我想做的事情 然而,我的前置函数没有被调用,只是被忽略了。 发生什么事了 这是我的补丁:Ruby使用prepend修补类不';行不通,ruby,monkeypatching,prepend,Ruby,Monkeypatching,Prepend,我正在尝试修补sinatra中的动词方法,以便在其之前添加额外的函数调用。我在使用别名链来保留原始方法时遇到了问题,但我发现prepend允许我在不使用这种黑客方法的情况下做我想做的事情 然而,我的前置函数没有被调用,只是被忽略了。 发生什么事了 这是我的补丁: if defined? Sinatra::Base module Restman module Patches module Sinatra_Base_Patch
if defined? Sinatra::Base
module Restman
module Patches
module Sinatra_Base_Patch
[:get, :post, :put, :delete, :head, :options, :patch, :link, :unlink].each do |func_name|
define_method func_name do |*args,&block|
if args.first.class == Symbol
super(Restman::Routes.get(args.first)[:uri],*block)
else
super(*args,*block)
end
end
end
end
end
end
::Sinatra::Base.prepend Restman::Patches::Sinatra_Base_Patch
end
编辑:(解释)
该补丁非常简单,它覆盖sinatra的正常HTTP谓词方法,并检查是否向其传递了符号,如果传递了符号,则将符号传递给返回映射的方法,并从映射中取出url,然后将其传递给sinatra的正常HTTP谓词方法
这样我就可以:
Restman::Routes.define do
map :root, to: '/'
end
然后呢
get :root do
'hello world!'
end
我正在考虑尝试改进,这样可能会更好。。可能?获取,
发布
,放置
等。Sinatra中的方法是类方法,但您正在使用这些名称创建实例方法。为了拦截这些方法,您需要在Sinatra::Base
singleton类前面加上前缀
试试这个:
::Sinatra::Base.singleton_class.prepend Restman::Patches::Sinatra_Base_Patch
您能否以一种不需要我们编写Sinatra web应用程序来调试代码的方式重现问题?我现在甚至没有安装Sinatra。你确定monkeypatch应用正确吗?添加一些puts语句以了解发生了什么我不知道老实说,prepend应该允许我在不直接打开原始类的情况下运行monkey patch,我遵循了示例,但它的工作方式与我预期的不一样(请参阅op edit了解此补丁的功能)。我确实尝试过使用put,但是函数根本没有被调用,所以没有输出任何get。奇怪的是,另一个使用
prepend
的类补丁确实有效;我知道是这样的,因为我的一个类使用了一个修补过的类方法,它不会发出嘶嘶的声音说这个方法不存在(如果修补失败,它会这样)。我尝试过使用define\u singleton\u method
没有效果,但我明天也会尝试。这很有效,我不知道为什么define\u singleton\u method
没有,但我不在乎,singleton\u类。prepend
有效,这对我来说已经足够了!