【发布时间】:2015-05-11 18:19:09
【问题描述】:
我正在尝试修补 sinatra 中的动词方法,以便在它之前添加一个额外的函数调用。我在使用别名链来保留原始方法时遇到了问题,但我发现 prepend 可以让我在不使用这种 hacky 方法的情况下做我想做的事。
但是我的前置函数没有被调用,只是被忽略了。 怎么回事?
这是我的补丁:
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 Web 应用程序来调试您的代码的方式重现该问题?目前我什至没有安装 Sinatra。 stackoverflow.com/help/mcve
-
您确定monkeypatch 应用正确吗?添加一些 puts 语句以了解发生了什么
-
老实说,我不知道,prepend 应该允许我在不直接打开原始类的情况下进行猴子补丁,我按照示例进行操作,但它没有像我期望的那样工作(请参阅操作编辑这个补丁做了什么)。我确实尝试过使用 put,但该函数根本没有被调用,所以没有输出任何东西。不过奇怪的是,我使用
prepend进行的其他类修补工作了;我知道它确实如此,因为我有一个类使用了修补的类方法,并且它不会抛出一个嘶嘶作响的说法,说该方法不存在(如果修补失败,它会这样)。
标签: ruby monkeypatching prepend