如何通过prepend修补ActionView模块?

时间:2016-11-01 08:47:58

标签: ruby-on-rails ruby monkeypatching prepend

如果在类<section class="services"> <div class="left skew"> <div class="inner-container"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Porro praesentium deserunt fugiat, qui est delectus vel eligendi totam quidem amet laudantium harum, saepe voluptates voluptatibus. Aliquam ea, totam nulla magni.</p> </div> </div> <div class="right skew"> </div> </section>中包含模块Foo,然后将该模块添加到另一个模块SomeClass,则Bar内的任何方法覆盖都不会生效Bar。例如:

SomeClass

我试图通过以下方式修补ActionView帮助程序方法:

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'

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 已经被包含在内(在应该包含的任何地方),因此前缀似乎没有生效。有人知道解决方案吗?

1 个答案:

答案 0 :(得分:1)

如果不回答有关模块前置的具体问题,可以采用另一种方式:

由于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,因为我不需要在辅助模块中对继承链进行硬编码。