Ruby, использующий prepend для исправления класса, не работает

Я пытаюсь исправить методы глагола в Sinatra, чтобы добавить перед ним дополнительный вызов функции. У меня были проблемы с использованием цепочки псевдонимов для сохранения исходных методов, но я обнаружил, что prepend позволяет мне делать то, что я хочу, без использования такого хакерского метода.

Однако мои предварительно добавленные функции не вызываются и просто игнорируются. в чем дело?

Вот мой патч:

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

РЕДАКТИРОВАТЬ: (объяснение)

Патч довольно прост, он переопределяет обычные методы HTTP-глагола Sinatra и проверяет, был ли ему передан символ или нет, если он был, он передает символ методу, который возвращает сопоставление и извлекает URL-адрес из сопоставления, а затем передает это обычным HTTP-методам Sinatra.

Это так, что я могу:

Restman::Routes.define do
  map :root, to: '/'
end

а затем сделать

get :root do
 'hello world!'
end

Я думаю о том, чтобы попробовать уточнения, которые могут работать лучше .. может быть?


person Thermatix    schedule 11.05.2015    source источник
comment
Можете ли вы воспроизвести проблему таким образом, чтобы нам не требовалось писать веб-приложение Sinatra только для отладки вашего кода? На данный момент у меня даже не установлена ​​Синатра. stackoverflow.com/help/mcve   -  person Jörg W Mittag    schedule 11.05.2015
comment
вы уверены, что мартышкин патч применен правильно? добавьте несколько операторов puts, чтобы узнать, что происходит   -  person phoet    schedule 11.05.2015
comment
Я не знаю, если честно, предполагается, что prepend позволит мне установить патч без прямого открытия исходного класса, я последовал примеру, но он не работает так, как я ожидаю (см. op edit для того, что делает этот патч). Я пытался использовать put, но функция вообще не вызывается, поэтому ничего не выводится. Как ни странно, другое исправление класса с использованием prepend у меня сработало; Я знаю, что это произошло, поскольку класс, который у меня есть, использует исправленный метод класса, и он не вызывает шипение, говоря, что метод не существует (что было бы, если бы исправление не удалось).   -  person Thermatix    schedule 11.05.2015


Ответы (1)


Методы get, post, put и т. д. в Sinatra являются методами класса, но вы создаете методы экземпляра с такими именами. Чтобы перехватить методы, вам нужно добавить класс синглтона Sinatra::Base.

Попробуй это:

::Sinatra::Base.singleton_class.prepend Restman::Patches::Sinatra_Base_Patch
person matt    schedule 11.05.2015
comment
Я пытался использовать define_singleton_method безрезультатно, но я попробую и это завтра. - person Thermatix; 12.05.2015
comment
Это сработало, я не знаю, почему define_singleton_method нет, но мне все равно, singleton_class.prepend сработало, и этого мне достаточно! - person Thermatix; 12.05.2015