如果在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模块中硬编码继承链。