Ruby / Rails: как временно определить область действия для вызова методов - PullRequest
1 голос
/ 11 мая 2011

У меня есть модуль:

module LiquidFilters
  include ActionView::Helpers::AssetTagHelper

  def stylesheet_tag(stylesheet_file_path)
    stylesheet_link_tag stylesheet_file_path
  end
end

И моя спецификация:

describe LiquidFilters do
  describe "#stylesheet_tag" do
    it "should return the css file in an html (media=screen) tag" do
      helper.stylesheet_tag("/path/css").should match(/<link href="\/path\/css\.css" media="screen" rel="stylesheet" type="text\/css"\s*\/>/)
    end
  end
end

Но я получаю неверное количество аргументов (2 для 1) ошибка:

Failures:
  1) LiquidFilters#stylesheet_tag should return the css file in an html (media=screen) tag
     Failure/Error: helper.stylesheet_tag("/path/css").should match(/<link href="\/path\/css\.css" media="screen" rel="stylesheet" type="text\/css"\s*\/>/)
     wrong number of arguments (2 for 1)
     # ./app/filters/liquid_filters.rb:16:in `stylesheet_tag'
     # ./spec/helpers/liquid_filters_spec.rb:13

Я вижу, что проблема в stylesheet_link_tag stylesheet_file_path в модуле LiquidFilters - stylesheet_link_tag должен вызывать закрытый метод AssetTagHelper "stylesheet_tag" ,но в итоге он вызывает LiquidFilter stylesheet_tag метод.

Вопрос

Как заставить stylesheet_link_tag вызывать AssetTagHelper методы, а не LiquidFilter s?

Примечание: я хотел бы сохранить имя метода stylesheet_tag.

Ответы [ 2 ]

1 голос
/ 11 мая 2011

Вы можете включить модуль AssetTagHelper в класс Helper, чтобы избежать переопределения имени метода, например:

require 'singleton'

module LiquidFilters
  class Helper
    include Singleton  
    include ActionView::Helpers::AssetTagHelper
  end

  def stylesheet_tag(stylesheet_file_path)
    Helper.instance.stylesheet_link_tag stylesheet_file_path
  end
end

Таким образом, ваш stylesheet_tag метод не будет перепутан с приватным методом AssetTagHelper.

Редактировать

Судя по вашим отзывам, я думаю, это самое близкое, что вы получите:

module LiquidFilters
  include ActionView::Helpers::AssetTagHelper

  alias :old_stylesheet_tag :stylesheet_tag

  def stylesheet_tag(stylesheet_file_path, options = nil)
    if options
      old_stylesheet_tag(stylesheet_file_path, options)
    else
      stylesheet_link_tag stylesheet_file_path
    end 
  end 
end

Вы в основном переопределяете закрытый метод, поэтому я не думаю, что есть какая-либо другая альтернатива, кроме прокси-вызовов.

0 голосов
/ 11 мая 2011

Rails's alias_method_chain может помочь:

module LiquidFilters
  include ActionView::Helpers::AssetTagHelper

  def stylesheet_tag_with_liquid(stylesheet_file_path, options = nil)
    # if this got called with two arguments, proxy them to original
    if options
      stylesheet_tag_without_liquid(stylesheet_file_path, options)
    else
      stylesheet_link_tag stylesheet_file_path
    end
  end

  def self.included(receiver)
    alias_method_chain :stylesheet_tag, :liquid
  end
end

Пока вы все еще маскируете оригинальный метод, теперь вы можете использовать прокси к нему.

EDIT: перемещен alias_method_chain в self.included обратный вызов, поэтому он не будет вызываться до того, как модуль будет фактически включен куда-либо.

...