2012-09-22 49 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