【问题标题】:Multiple content_for on the same page同一页面上有多个 content_for
【发布时间】:2011-08-03 15:07:28
【问题描述】:

我的应用程序中有大块 HTML,我想将其移动到共享模板中,然后使用 content_for 和 yield 来插入必要的内容。但是,如果我在同一个布局文件中多次使用它, content_for 只会附加到前一个文件中,从而使该想法无法很好地发挥作用。有解决办法吗?

<div class="block side">
    <div class="block_head">
        <div class="bheadl"></div>
        <div class="bheadr"></div>
        <h2><%= yield :block_head %></h2>
    </div>
    <div class="block_content">
        <%= yield :block_content %>
    </div>
    <div class="bendl"></div>
    <div class="bendr"></div>
</div>

我使用下面的代码来设置块的内容

    <%= overwrite_content_for :block_head do -%>
        My Block
    <% end -%>
    <%= overwrite_content_for :block_content do -%>
        <p>My Block Content</p>
    <% end -%>
    <%= render :file => "shared/_blockside" %>

问题是如果我在同一个布局上多次使用它,来自原始块的内容会附加到辅助块

我尝试创建一个自定义帮助方法来绕过它,但是它不返回任何内容

  def overwrite_content_for(name, content = nil, &block)
    @_content_for[name] = ""
    content_for(name, content &block)
  end

我也可能完全错了,如果有更好的方法让内容像这样工作,我想知道。谢谢。

【问题讨论】:

    标签: ruby-on-rails-3 yield content-for


    【解决方案1】:

    您可以像这样使用命名为 content_foryield 的块:

    查看:

    <% content_for :heading do %>
      <h1>Title of post</h1>
    <% end %>
    
    <p>Body text</p>
    
    <% content_for :footer do %>
      <cite>By Author Name</cite>
    <% end %>
    

    然后在一个布局中:

    <%= yield :heading %>
    <%= yield %>
    <%= yield :footer %>
    

    您当然可以按任意顺序定义它们。

    文档:http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html

    【讨论】:

      【解决方案2】:

      我不确定我是否真的理解您的问题 - 这是一种有效的代码方法:

      查看:

      <% content_for :one do %>
        Test one
      <% end %>
      
      <% content_for :two do %>
        Test two
      <% end %>
      
      <p>Hi</p>
      

      application.html.erb

      <%= yield :one %>
      <%= yield %>
      <%= yield :two %>
      

      Railsguides:http://guides.rubyonrails.org/layouts_and_rendering.html#using-content_for

      【讨论】:

      • 为什么投反对票?在我回答后,原始问题已被编辑。它现在包含更多细节......
      【解决方案3】:

      您应该将您的 overwrite_content_for 定义如下(如果我正确理解您的问题):

        def overwrite_content_for(name, content = nil, &block)
          content = capture(&block) if block_given?
          @_content_for[name] = content if content
          @_content_for[name] unless content
        end
      

      请注意,如果您的块产生 nil,则旧内容将被保留。但是,整个想法听起来并不好,因为您显然要进行两次渲染(或至少是对象实例化)。

      【讨论】:

      • 这成功了,谢谢。我确实理解渲染两次的问题,但似乎使用 content_for 和布局比在我需要它显示的任何地方粘贴大块 HTML 更可取。
      • 你就不能用简单的部分吗?
      • 好吧,在某些情况下,我会将大量 HTML 内容传递到 :block_content 产量中。不知道我将如何使用部分实现。
      • 好吧,基本上如果这个 HTML 是静态的,那么它可能应该进入部分,如果它是动态的,那么它的帮助。
      【解决方案4】:

      您总是可以直接传递内容而不依赖于块:

      <% content_for :replaced_not_appended %>
      

      【讨论】:

        【解决方案5】:

        在 Rails 4 中,您可以传递 :flush 参数来覆盖内容。

        <%= content_for :block_head, 'hello world', :flush => true %>
        

        或者,如果你想传递一个块,

        <%= content_for :block_head, :flush => true do %>
          hello world
        <% end %>
        

        参见。这个助手的source code了解更多详情

        【讨论】:

        猜你喜欢
        • 2020-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-24
        • 2015-10-02
        相关资源
        最近更新 更多