Переопределение рельсовых помощников с доступом к оригинальным
Я хочу использовать знакомых помощников рельсов, но с немного измененными функциями. То, как я это вижу, хочу, чтобы я мог сделать что-то вроде:
module AwesomeHelper
#... create alias of stylesheet_link_tag to old_stylesheet_link_tag
def stylesheet_link_tag(*args)
if @be_awesome
awesome_stylesheet_link_tag *args
else
old_stylesheet_link_tag *args
end
end
end
Как я вижу это, у меня есть три варианта:
- Патч обезьяны:. Повторное открытие вспомогательного модуля рельсов. Если команда rails когда-либо изменяет имя своего вспомогательного модуля, мой код становится источником хрупкости. Не непреодолимый, но не идеальный.
- Использовать разные имена методов: Попытка придерживаться общего интерфейса rails может быть моим падением. Мои изменения могут стать источником путаницы для других разработчиков.
- Способы отсоединения (новые): Не уверен, будет ли это работать, или будет ли он иметь те же недостатки, что и 1. Будет ли это исследовать, но это может быть хорошей отправной точкой.
Итак, вопрос здесь в том, что я придерживаюсь одного из этих субоптимальных решений или есть другой способ, который я не рассматривал? Если я перейду на вариант 3, есть ли способ сделать это, не обращаясь напрямую к вспомогательному модулю rails?
(Примечание: я удалил контекст, так как он ничего не добавляет к вопросу.)
Ответы
Ответ 1
Там лучший способ, чем любой из перечисленных вами вариантов. Просто используйте super
:
module AwesomeHelper
def stylesheet_link_tag(*sources)
if @be_awesome
awesome_stylesheet_link_tag *sources
else
super
end
end
end
Переопределение stylesheet_link_tag
в AwesomeHelper гарантирует, что при вызове stylesheet_link_tag
Ruby встретит его в пути поиска метода до того, как он достигнет ActionView::Helpers::AssetTagHelper
. Если @be_awesome
- true
, вы можете взять на себя ответственность и остановить все там, а если нет, вызов super
без круглых скобок будет прозрачно проходить через все аргументы до реализации Rails. Таким образом, вам не нужно беспокоиться о том, что основная команда Rails перемещает вас на вас!
Ответ 2
Я не использую этот драгоценный камень, поэтому я отвечу вам более общим образом.
Предположим, вы хотите записывать вызовы на link_to
helper (да, надуманный пример, но показывает идею). В API-интерфейсе вы понимаете, что link_to
находится внутри модуля ActionView::Helpers::UrlHelper
. Таким образом, вы создаете файл в каталоге, скажем, config/initializers
со следующим содержимым:
# like in config/initializers/link_to_log.rb
module ActionView::Helpers::UrlHelper
def link_to_with_log(*args, &block)
logger.info '**** LINK_TO CALL ***'
link_to_without_log(*args, &block) # calling the original helper
end
alias_method_chain :link_to, :log
end
Ядро этой функциональности - alias_method_chain
(доступно для кликов). Используйте его ПОСЛЕ определения метода xxx_with_feature
.
Ответ 3
Попробуйте использовать alias_method
:
module AwesomeHelper
alias_method :original_stylesheet_link_tag, :stylesheet_link_tag
def stylesheet_link_tag(*sources)
if @be_awesome
awesome_stylesheet_link_tag *sources
else
original_stylesheet_link_tag *sources
end
end
end
Ответ 4
Я бы очень хотел, чтобы вы рассмотрели свой вариант № 2, переопределив поведение методов рельсов так, как это очевидно для вызывающего.
Ваш новый метод должен быть вызван awesome_stylesheet_link_tag
, чтобы другие разработчики Rails могли прочитать ваш код и задать вопрос "Что такого удивительного в теге ссылки?".
В качестве меньшего изменения вы можете сделать переопределение, но передать в :awesome => true
в качестве аргумента, чтобы они, по крайней мере, имели представление о том, что что-то происходит.
Изменение поведения широко используемого метода, такого как stylesheet_link_tag
, создает потенциальное будущее недоразумение, когда нет необходимости.