If you include a module Foo
in a class SomeClass
, then prepend that module with another module Bar
, any method-overwriting inside Bar
will not take effect in SomeClass
. Example:
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'
I am trying to monkey-patch an ActionView helper method the following way:
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
and then in an initializer:
ActionView::Helpers::UrlHelper.prepend CoreExtensions::ActionView::Helpers::UrlHelper::SecureLinkTo
However, this doesn't seem to work. My assumption - by the time the initializer executes, ActionView::Helpers::UrlHelper
has already been included (in wherever it is supposed to be included) and thus the prepending doesn't seem to take effect. Does anybody know a solution to this?
Without answering your specific question about module prepend, here would be another way:
Since helpers in Rails are global, you can simply create your own helper with the link_to
method overridden.
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
Somehow this seems less hacky
than creating an initializer, because I don't need to hardcode the inheritence chain in the helper module.