2

我有一個類多級塊方法產生問題

class DataListBuilder 
    include ActionView::Helpers::TagHelper 
    include ActionView::Helpers::CaptureHelper 
    include ActionView::Helpers::UrlHelper 
    attr_accessor :object, :output_buffer 

    def initialize(object) 
     @object, @output_buffer = object, nil 
    end 

    def column (&block) 
     if block_given? 
     content_tag(:li, block.call(self)) 
     else 
     content_tag(:li, "") 
     end 
    end 

    def options_column(&link_block) 
     if block_given? 
     content_tag(:li, content_tag(:dl, "<dt><a href='#'>&nbsp;</a></dt><dd><ul>#{link_block.call(self)}</ul></dd>".html_safe, :class=>'options')) 
     else 
     content_tag(:li, "") 
     end 
    end 

    def link_item(title, url, options={}) 
     content_tag :li, link_to(title, url, options) 
    end 
    end 

,把它作爲

<%= l.options_column do |c| %> 
     <%= c.link_item 'Show', lead_path(c.object) %> 
     <%= c.link_item 'Edit', edit_lead_path(c.object) %> 
     <%= c.link_item 'New Note', "leads/#{c.object.id}/notes/new", :class=>"display-newxdoc", :id=>c.object.id %> 
     <%= c.link_item 'Create Opportunity', new_lead_opportunity_path(c.object) %> 
    <% end %> 

期望的輸出是

<li><dl class="options"><dt><a href="#">&nbsp;</a></dt><dd><ul style="display: none;"> 
    <li><a data-remote="true" class="plus" href="leads/details/309">&nbsp;</a></li> 
    <li>3w</li> 
    <li>Simon Wu</li> 
    <li>1-714-553-0888</li> 
    <li>[email protected]</li> 
    <li>Unified Beat</li> 

     <li><a href="/leads/309">Show</a></li> 
     <li><a href="/leads/309/edit">Edit</a></li> 
     <li><a id="309" class="display-newxdoc" href="leads/309/notes/new">New Note</a></li> 
     <li><a href="/leads/309/opportunities/new">Create Opportunity</a></li> 

但它產生

<li><a href="/leads/309">Show</a></li> 
<li><a href="/leads/309/edit">Edit</a></li> 
<li><a id="309" class="display-newxdoc" href="leads/309/notes/new">New Note</a></li> 
<li><a href="/leads/309/opportunities/new">Create Opportunity</a></li> 
<li><dl class="options"><dt><a href="#">&nbsp;</a></dt><dd><ul style="display: none;"> 
    <li><a data-remote="true" class="plus" href="leads/details/309">&nbsp;</a></li> 
    <li>3w</li> 
    <li>Simon Wu</li> 
    <li>1-714-553-0888</li> 
    <li>[email protected]</li> 
    <li>Unified Beat</li> 

     <li><a href="/leads/309">Show</a></li> 
     <li><a href="/leads/309/edit">Edit</a></li> 
     <li><a id="309" class="display-newxdoc" href="leads/309/notes/new">New Note</a></li> 
     <li><a href="/leads/309/opportunities/new">Create Opportunity</a></li> 
</ul></dd></dl></li> 
    </ul></dd></dl></li> 

任何人都可以幫助我。

已完成代碼here

回答

4

首先,我們重構你的幫手的content_tag更密集的使用(只是爲了讓這個代碼裏究竟是怎麼回事^ _ ^)。

接下來我們添加使用output_buffer這是已定義,但完全沒有在助手使用。

之後它應該從erb調用所有的方法應返回nil所以他們沒有出現在HTML中。

最後的句法結構是instance_eval的用法,因此您不需要{|c| ...}樣式塊。您可以直接使用DataListBuilder中的所有變量。

module DataListHelper 
    def list_headers(args=[]) 
    args = Array.new(args) 
    columns = [] 
    args.map { |o| columns << content_tag(:li, o.split(":").first, :style=>"width:#{o.split(":").second}px;") } 
    content_tag(:ul, columns.join(" ").html_safe, :class=>"list-headers") 
    end 

    def data_list_total_records(array) 
    content_tag(:div, page_entries_info(array).html_safe, :class=>"total-records") 
    end 

    def data_list_for(object, headers=[], &block) 

    if object.is_a? Array 
     if object.length == 0 
     list_headers(headers).concat(content_tag(:strong, "<br />No records found".html_safe)) 
     else 
     res_obj = data_list_total_records(object) 
     res_obj << content_tag(:ol, :class=>"data-list") do 
      res_ol = content_tag(:li) do 
      res = list_headers(headers) 
      object.each do |o| 
       builder = DataListBuilder.new(o) 
       res << content_tag(:li) do 
       content_tag(:ul, :id=>o.id, :class=>"list-row #{cycle('odd', 'even')}") do 
        capture(builder, &block) 
        builder.output_buffer.html_safe 
       end 
       end 
      end 
      res 
      end 
      res_ol << data_list_pagination(object) 
     end 
     res_obj 
     end 
    else 
     list_headers(headers).concat(content_tag(:strong, " <br />Not available.")) 
    end 
    end 

    class DataListBuilder 
    include ActionView::Helpers::TagHelper 
    include ActionView::Helpers::CaptureHelper 
    include ActionView::Helpers::UrlHelper 
    include Rails.application.routes.url_helpers 

    attr_accessor :object, :output_buffer, :controller 

    def initialize(object) 
     @object, @output_buffer = object, '' 
    end 

    def column (&block) 
     @output_buffer << if block_given? 
     content_tag(:li, instance_eval(&block)) 
     else 
     content_tag(:li, "") 
     end 
     nil 
    end 

    def options_column(&link_block) 
     @output_buffer << if block_given? 
     content_tag(:li) do 
      content_tag(:dl, :class=>'options') do 
      res = content_tag(:dt) do 
       content_tag(:a, '&nbsp;'.html_safe, :href => '#') 
      end 
      res << content_tag(:dd) do 
       content_tag(:ul) do 
       instance_eval &link_block 
       end 
      end 
      end 
     end 
     else 
     content_tag(:li, "") 
     end 
     nil 
    end 

    def link_item(title, url, options={}) 
     content_tag :li, link_to(title, url, options) 
    end 
    end 
end 

而且你的看法變成了這樣:

<%= data_list_for @leads, [" :10", "Age:30", "Contact:140", "Phone:140", "Email:180", "Company:100", ""] do |l| %> 
    <%= l.column { link_to "&nbsp;".html_safe, "leads/details/#{object.id}", :class=>:plus, :remote=>true } %> 
    <%= l.column { object.age } %> 
    <%= l.column { object.contact.complete_name } %> 
    <%= l.column { object.contact.phones.blank? ? "-" : object.contact.phones.first.phone_number } %> 
    <%= l.column { object.contact.emails.blank? ? "-" : object.contact.emails.first.email } %> 
    <%= l.column { object.company.title } %> 
    <%= l.options_column do %> 
     <%= link_item 'Show', lead_path(object.id) %> 
     <%= link_item 'Edit', edit_lead_path(object.id) %> 
     <%= link_item 'New Note', "leads/#{object.id}/notes/new", :class=>"display-newxdoc", :id=>object.id %> 
     <%= link_item 'Create Opportunity', new_lead_opportunity_path(object.id) %> 
    <% end %> 
<% end %> 
+0

真的真的非常感謝。有用。這也讓我完全瞭解正在發生的事情和內在的事情。現在唯一的問題是'lead_path(object)'和路由方法不起作用。它產生錯誤'ActionView :: Template :: Error(未定義的方法'lead_path'爲#):'。 這是唯一留在列表中的東西。請幫忙解決它。 – 2011-04-07 07:02:59

+0

@Nazar Huaain - 我更新了答案,以解決您的問題與鏈接。將'Rails.application.routes.url_helpers'和屬性'controller'添加到'DataListBuilder'中。在視圖中添加了'object.id'。 http://stackoverflow.com/questions/341143/can-rails-routing-helpers-i-e-mymodel-pathmodel-be-used-in-models/5456103#5456103瞭解更多信息 – 2011-04-07 07:39:49

+0

非常感謝。這解決了我的問題。 – 2011-04-07 08:53:05

0

options_column是一個「塊視圖」,我想刪除= <%= l.options_column do |c| %>,這是肯定的。然後,我會在options_column中使用concat,而不是直接以字符串形式返回它。

無論如何,簡單的解決方案是在這裏(我用它,沒有問題的話):

https://github.com/markevans/block_helpers

+0

這實在是太棒了。但我有問題。我們怎樣才能讓這樣的幫助者迭代一些集合。我無法找到您建議的幫助程序的wiki上的任何示例或方法。請給我任何例子。 – 2011-04-07 12:46:17