2012-09-22 48 views
0

我正在制作一个样式指南,其中我在左侧显示的右侧输出代码。将ERB作为HTML和ERB从Rails视图呈现

我知道加入%%逃脱ERB

我写了一个帮手,需要一个块的内容,并呈现代码在两个地方一个显示HTML和我想让对方显示源ERB是创建了html。

问题是我找回了我想要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 

预期结果 按钮<%=的link_to “按钮”, “/ style_guide,等级:” BTN “%>

实际结果 按钮按钮

干杯

回答

0

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

在我看来,你的选择是:

  1. 打出去的例子为谐音,然后做一个助手,一个)呈现局部和b)显示基础文件。
  2. 将ERB片段指定为字符串(heredocs?),将该字符串传递给助手,并让助手a)通过ERB.new(string).result(binding)对其进行评估以显示结果并显示字符串。
  3. 使帮助程序确定视图的哪部分调用它,然后足够好地解析.erb以查找块。 Catch是,由于视图编译的方式,您在callers中看到的确切格式如有更改,恕不另行通知。
  4. 建立一个帮助器,使用疯狂元编程juju评估ERB上下文中的块以及您自己的特殊上下文,该上下文拦截正在评估的代码并将其重新转换为标记。

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

0

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

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