【问题标题】:Multi level block method is generating issue多级块方法正在产生问题
【发布时间】:2011-04-06 07:09:10
【问题描述】:

我有课

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>omnisw@unifiedbeat.com</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>omnisw@unifiedbeat.com</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

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-plugins


    【解决方案1】:

    首先,我们重构了您的助手,以便更密集地使用content_tag(只是为了了解这段代码的内容^_^)。

    接下来我们添加 output_buffer 的用法,它在 helper 中已定义但根本没有使用。

    之后,应该从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 %>
    

    【讨论】:

    • 真的真的真的非常感谢。有用。它也让我对正在发生的事情和内部情况有了完整的了解。现在唯一的问题是lead_path(object) 和路由方法不起作用。它会为 #<:datalistbuilder:0xef8c3bc>):` 生成错误 ActionView::Template::Error (undefined method lead_path'。这是列表中唯一剩下的东西。请帮忙解决。
    • @Nazar Huaain - 我更新了答案以解决您的链接问题。在DataListBuilder 中添加了include Rails.application.routes.url_helpers 和属性controller。将object.id 添加到视图中。 stackoverflow.com/questions/341143/… 了解更多信息
    【解决方案2】:

    options_column 是“块视图”,我会删除 &lt;%= l.options_column do |c| %&gt; 中的 =,这是肯定的。然后,我会在options_column 中使用concat,而不是直接将其作为字符串返回。

    不管怎样,简单的解决方案就在这里(我用过,完全没有问题):

    https://github.com/markevans/block_helpers

    【讨论】:

    • 真的很棒。但我对此有疑问。我们如何制作这样的块助手来迭代一些集合。我在您建议的助手的 wiki 上找不到任何示例或方法。请给我任何例子。
    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2015-02-23
    相关资源
    最近更新 更多