Переопределение базового метода mixin в Rails и возможность вызова старого метода
-
06-07-2019 - |
Вопрос
Хорошо, название озадачивает. Сначала я расскажу о своей проблеме.
метод polymorphic_url
был изменен в Rails 2.2.1, чтобы включить некоторые дополнительные функциональные возможности, которые мне нужны. Однако я хочу, чтобы приложение продолжало работать в более старых версиях Rails, поэтому я хотел установить патч на поведение 2.2.1, если запущена более старая версия Rails.
alias_method_chain
право на спасение? Я не могу заставить его работать.
def polymorphic_url_with_compat(*args)
whatever...
return polymorphic_url(*args)
end
alias_method_chain :polymorphic_url, :compat
Теперь я сначала попытался поместить это в помощник - alias_method_chain
завершился неудачно, потому что polymorphic_url
к тому времени не определено.
Таким образом, я переместил тот же код в контроллер, и это не ошибка, но он игнорируется.
Затем я попытался пропатчить его в ApplicationController :: Base с помощью плагина - polymorphic_url
по-прежнему не определен.
polymorphic_url
определяется в модуле ActionController :: PolymorphicRoutes. Я действительно не знаю, когда / где это смешано с контроллером / представлением. Р>
Как я могу обернуть этот метод так, как я хочу?
Решение
Прежде чем мы продолжим, вы уверены, что polymorphic_url существовал в версии Rails до 2.2.1?
Ваш код в основном правильный, вы забываете вызывать оригинальную версию метода. Который переименован в polymorphic_url_without_compat после вызова alias_method_chain.
class ActiveRecord::PolymorphicRoutes
def polymorphic_url_with_compat(*args)
whatever...
return polymorphic_url_without_compat(*args)
end
alias_method_chain :polymorphic_url, :compat
end
Вы упомянули, что пытались добавить его в плагин, поэтому следующее может не понадобиться, если предыдущий бит исправил вашу проблему. Р>
Лучший способ убедиться, что он загружен после ядра рельсов, это превратить его в плагин.
$ script/generate plugin polymorphic_url_backport
Создаю заглушку плагина. Все указания с этого момента относятся к созданному каталогу плагинов.
В init.rb добавить
if RAILS_GEM_VERSION < "2.2.1"
require File.dirname(__FILE__) + '/lib/yournamespace'
ActionController::PolymorphicRoutes.send(:include, YourNameSpace::ActionController::PolymorphicRoutes)
end
Затем вставьте приведенный выше код в ваш lib / yournamespace.rb
module YourNameSpace
class ActiveRecord::PolymorphicRoutes
def included(base)
base.class_eval %~
def polymorphic_url_with_compat(*args)
whatever...
return polymorphic_url_without_compat(*args)
end
alias_method_chain :polymorphic_url, :compat
~
end
end
end
Просто убедитесь, что плагин поставляется с вашим приложением, и проблем не должно быть. Вы можете поочередно добавить это в библиотеку своего корневого каталога rails, но я не уверен, где именно вы разместите код, необходимый для его запуска в нужное время. Р>