【问题标题】:Render ERB as HTML and ERB from a Rails View从 Rails 视图将 ERB 渲染为 HTML 和 ERB
【发布时间】:2012-09-22 04:01:59
【问题描述】:

我正在制作一个样式指南,我在其中输出右侧显示在左侧的代码。

我知道添加 %% 会转义 ERB

我编写了一个助手,它获取块的内容并在两个地方呈现代码,一个显示 html,我希望另一个显示创建 html 的源 ERB。

问题是我在我想要 ERB 的地方返回 HTML。

查看代码

<%= display_code do %>
  <%= link_to "Button", "/style_guide, class: "btn" %>
<% end %>

助手代码

module StyleGuideHelper
  def display_code(&block)
    content = with_output_buffer(&block)
    html = ""
    html << content_tag(:div, content, class: "rendered-code")
    html << content_tag(:div, escape_erb(content), class: "source-code-preview")
    html.html_safe
  end

  def escape_erb(code)
    code = code.gsub("%=", "%%=")
  end
end

预期结果 按钮

实际结果 按钮按钮

干杯

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2 erb


    【解决方案1】:

    问题是这个帮助程序运行块 (link_to "Button", ...)——它永远不会看到块内的源代码,只看到它的输出。您可以将 escape_erb 替换为 h 以捕获生成的 HTML,但这不会弹出到生成它的 ERB。

    在我看来,您的选择是:

    1. 将示例分解为部分,然后创建一个帮助程序来 a) 呈现部分内容并 b) 显示基础文件。
    2. 将您的 ERB 片段指定为字符串(heredocs?),将字符串传递给助手,并让助手 a) 通过 ERB.new(string).result(binding) 对其进行评估以呈现结果并 b) 显示字符串。
    3. 让助手确定视图的哪个部分调用了它,然后解析 .erb 以找到该块。需要注意的是,您在 callers 中看到的内容的精确格式可能会因视图的编译方式而发生更改,恕不另行通知。
    4. 创建一个助手,使用疯狂的元编程 juju 在 ERB 上下文以及您自己的特殊上下文中评估块,拦截正在评估的代码并将其转换回标记。

    ...按照复杂性和成功几率的大致顺序排序。

    【讨论】:

    • 我实际上正在搜索选项 1 的配方。
    【解决方案2】:

    下面的代码将允许您检索给定块的代码。

    class ERBSource
      ERB = ::ActionView::Template::Handlers::ERB
    
      def self.for(block)
        new(block).source
      end
    
      attr_reader :block, :file, :line_number
      def initialize(block)
        @block = block
        @file, @line_number = *block.source_location
      end
    
      def source
        lines = File.readlines(file)
    
        relevant_lines = lines[(line_number - 1)..-1] || []
    
        extract_first_expression(relevant_lines)
      end
    
      private
    
      def extract_first_expression(lines)
        code = lines.slice[0,1].join # add the first two lines so it has to iterate less
    
        lines.each do |line|
          code << line
          return code if correct_syntax?(compile_erb(code))
        end
        raise SyntaxError, "unexpected $end"
      end
    
      def correct_syntax?(code)
        stderr = $stderr
        $stderr.reopen(IO::NULL)
        RubyVM::InstructionSequence.compile(code)
        $stderr.reopen(stderr)
        true
      rescue Exception
        $stderr.reopen(stderr)
        false
      end
    
      def compile_erb(code)
        ERB.erb_implementation.new(
          code,
          :escape => false,
          :trim => (ERB.erb_trim_mode == "-")
        ).src
      end
    end
    

    这是助手的样子

    module StyleGuideHelper
      def render_example(name, &block)
        code = ERBSource.for(block)
        content_tag(:h2, name) +
          content_tag(:div, &block) +
          content_tag(:pre, content_tag(:code, code))
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-24
      • 1970-01-01
      相关资源
      最近更新 更多