通过访问原始文件覆盖rails帮助程序

我想使用rails熟悉的助手,但function略有改变。 我看待它的方式,我希望能够做到这样的事情:

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 

我看到它的方式,我有三个选择:

  1. 猴子修补:重新打开rails helper模块。 如果rails团队改变了他们的帮助器模块的名称,我的代码就变成了脆弱的来源。 不是不可克服的,但并不理想。
  2. 使用不同的方法名称:试图坚持共轨接口可能是我的垮台。 我的更改可能会成为其他开发人员混淆的根源
  3. 分离方法(新):不确定这是否有效,或者它是否会有与1相同的缺点。研究这个,但这可能是一个很好的起点。

所以这里的问题是,我是否坚持使用其中一种次优解决方案,还是有其他方式我没有考虑过? 如果我选择选项3,有没有办法在不直接寻址rails helper模块的情况下执行此操作?

(注意:我删除了上下文,因为它没有添加任何问题。)

有比你列出的任何选项更好的方法。 只需使用super

 module AwesomeHelper def stylesheet_link_tag(*sources) if @be_awesome awesome_stylesheet_link_tag *sources else super end end end 

覆盖AwesomeHelper中的stylesheet_link_tag将确保在调用stylesheet_link_tag时,Ruby会在遇到ActionView::Helpers::AssetTagHelper之前在方法查找路径中遇到它。 如果@be_awesometrue ,你可以在那里负责并停止,如果没有,那么对没有括号的super的调用将透明地传递到Rails实现的所有参数。 这样你就不必担心Rails核心团队会在你身上移动东西!

我不使用这个gem,所以我会以更通用的方式回答你。

假设您要将调用记录到link_to帮助程序(是的,人为的例子,但显示了这个想法)。 查看API可让您了解位于ActionView::Helpers::UrlHelper模块内的link_to 。 因此,您可以在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 

此function的核心 – alias_method_chain (可点击)。 在定义方法xxx_with_feature之后使用它。

尝试使用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 

我真的鼓励你考虑你的选项#2,以一种对调用者来说显而易见的方式覆盖rails方法的行为。

您的新方法应该被称为awesome_stylesheet_link_tag以便其他Rails开发人员可以读取您的代码并询问“链接标记有什么awesome_stylesheet_link_tag ?”。

作为一个较小的变化你可以做覆盖,但传入:awesome => true作为参数,所以他们至少有一个线索,正在发生一些事情。

更改一个广泛使用的方法(如stylesheet_link_tag的行为会在不需要的地方产生潜在的未来误解。