如何通过prepend给ActionView模块打猴式补丁



如果在SomeClass类中包含模块Foo,然后在该模块前面加上另一个模块Bar,则Bar内部的任何方法覆盖将不会在SomeClass中生效。例子:

module Foo
  def some_method
    puts 'In Foo'
  end
end
class SomeClass
  include Foo
end
SomeClass.new.some_method # => 'In Foo'
module Bar
  def some_method
    puts 'In Bar'
    super
  end
end
Foo.prepend Bar
Foo.ancestors # => [Bar, Foo]
SomeClass.new.some_method # => 'In Foo'
class AnotherClass
  include Foo
end
AnotherClass.new.some_method # => 
# 'In Bar'
# 'In Foo'

我正在尝试猴子补丁一个ActionView助手方法如下:

In lib/core_extensions/action_view/helpers/url_helper/secure_link_to:

module CoreExtensions
  module ActionView
    module Helpers
      module UrlHelper
        module SecureLinkTo
          def link_to(name = nil, options = nil, html_options = nil, &block)
            html_options ||= {}
            if html_options[:target].present?
              html_options[:rel] = 'noopener noreferrer'
            end
            super(name, options, html_options, &block)
          end
        end
      end
    end
  end
end

,然后在初始化式中:

ActionView::Helpers::UrlHelper.prepend CoreExtensions::ActionView::Helpers::UrlHelper::SecureLinkTo

然而,这似乎不起作用。我的假设是——在初始化器执行的时候,ActionView::Helpers::UrlHelper已经被包含在内了(在它应该被包含的任何地方),因此前置似乎没有生效。有人知道这个问题的解决方法吗?

不回答您关于模块前置的具体问题,这里有另一种方法:

因为Rails中的帮助器是全局的,所以您可以简单地用覆盖link_to方法创建自己的帮助器。

module LinkHelper
  def link_to(name = nil, options = nil, html_options = nil, &block)
    html_options ||= {}
    if html_options[:target].present?
      html_options[:rel] = 'noopener noreferrer'
    end
    super(name, options, html_options, &block)
  end
end

这似乎比创建初始化器更少hacky,因为我不需要在helper模块中硬编码继承链。

相关内容

  • 没有找到相关文章

最新更新