Ruby使用prepend来修补一个类并不起作用

时间:2015-05-11 18:19:10

标签: ruby monkeypatching prepend

我试图在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

我想要尝试改进,这可能会更好......也许?

1 个答案:

答案 0 :(得分:1)

Sinatra中的getpostput等方法是类方法,但您正在创建实例方法用这些名字。为了拦截你需要预先添加Sinatra::Base单例类的方法。

试试这个:

::Sinatra::Base.singleton_class.prepend Restman::Patches::Sinatra_Base_Patch