2016-11-01 13 views
2

Если вы включили модуль Foo в класс SomeClass, тогда добавьте этот модуль с другим модулем Bar, любой метод-переписывание внутри Bar не вступит в силу в SomeClass. Пример:Как обезвредить модуль ActionView через preend?

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 Helper следующим образом:

В 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 уже был включен (там, где он должен быть включен), и, таким образом, предположение не вступает в силу. Кто-нибудь знает это решение?

+0

Почему бы просто не открыть «ActionView :: Помощники :: UrlHelper' и определить метод там? (кроме того, ваш подход кажется несколько более чистым) –

+0

Ну, точно так же, как вы говорите, я хотел бы сделать это чистым способом. Я следую этому: http://nofail.de/2014/06/monkey-patching-rails/, и эта статья рекомендует 'prepend' как лучшее решение. –

ответ

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, чем создание инициализатора, потому что не нужно жестко кодировать Наследование цепи в хелперовой модуле.

+0

Спасибо за ваш ансер, Магнусс. Где я могу поместить этот файл? –

+0

@AlexPopov Это простой старый вспомогательный модуль. Вы помещаете его в 'app/helpers'. – Magnuss

+0

Для справки: http://stackoverflow.com/questions/10471535/override-rails-helpers-with-access-to-original –