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