使用ActionView拦截模板内容

时间:2016-04-27 20:55:05

标签: ruby-on-rails actionview

我有一个Haml模板,周围散布着一堆“自定义标签”,例如{{REPLACE_ME}}。在渲染此模板之前,我将浏览模板并使用Ruby的String#gsub替换所有实例。

这不是问题 - 我只是简单地创建了一个自定义模板处理程序,它首先通过修改模板源然后将其传递给Haml模板处理程序充当中间人。

对于视图中每个“自定义标签”的出现,它会添加到存储在后台的分子中。然而,我所面临的问题是分子正在被提升,因为内容永远不会向用户显示,例如<% if false %>{{SECTION_NO}}<% end %>

在替换内容之前,应该过滤掉上述内容。然而,我似乎碰到了墙,因为Haml(和ERB)处理程序返回内容缓冲区而不是“结束/完成”内容。

这个问题是否有直接的解决方案?

以下是一个视图示例:

- if true
  %h1 {{SECTION_NO}}

- if false
  %h1 {{SECTION_NO}}

- if true
  %h1 {{SECTION_NO}}

所以基本上,在替换和计算“{{SECTION_NO}}”的出现之前,我需要一种方法来过滤掉视图源的中间(错误语句)。

作为参考,这是我为此目的创建的模板处理程序的要点:

class ActionView::Template::Handlers::Caml
  def initialize
    @section = 0
    @paragraph = 0
    @references = {}
  end

  def call(template)
    rendered_haml = ActionView::Template.registered_template_handler(:haml).call(template)

    updated_source = render_sections(rendered_haml)
    updated_source = render_paragraphs(updated_source)
    updated_source = render_references(updated_source)

    return ActionView::Template.new(
      updated_source,
      template.identifier,
      template.handler,
      {
        locals: template.locals,
        virtual_path: template.virtual_path,
        updated_at: template.updated_at
      }
    )
  end

  private

  def render_sections(source)
    source.gsub(/{{section:([a-zA-Z0-9-_]+)}}/).each do |match|
      fail 'Key already exists.' if @references.key?($1)
      @section += 1
      @references[$1] = "#{@section}"
      "#{@section}"
    end
  end

  def render_paragraphs(source)
    # ...
  end

  def render_references(source)
    source.gsub(/{{([a-zA-Z0-9-_]+)}}/).each do |match|
      @references.fetch($1)
    end
  end
end

ActionView::Template.register_template_handler(
  :caml,
  ActionView::Template::Handlers::Caml.new
)

0 个答案:

没有答案