【问题标题】:Rails render partial with blockRails 用块渲染部分
【发布时间】:2011-02-26 10:10:43
【问题描述】:

我正在尝试重新使用我编写的提供面板样式的 html 组件。比如:

  <div class="v-panel">
    <div class="v-panel-tr"></div>
    <h3>Some Title</h3>
    <div class="v-panel-c">
      .. content goes here
    </div>
    <div class="v-panel-b"><div class="v-panel-br"></div><div class="v-panel-bl"></div></div>
  </div>

所以我看到渲染需要一个块。我想我可以这样做:

# /shared/_panel.html.erb
<div class="v-panel">
  <div class="v-panel-tr"></div>
  <h3><%= title %></h3>
  <div class="v-panel-c">
    <%= yield %>
  </div>
  <div class="v-panel-b"><div class="v-panel-br"></div><div class="v-panel-bl"></div></div>
</div>

我想做类似的事情:

#some html view
<%= render :partial => '/shared/panel', :locals =>{:title => "Some Title"} do %>
  <p>Here is some content to be rendered inside the panel</p>
<% end %>

不幸的是,这不适用于此错误:

ActionView::TemplateError (/Users/bradrobertson/Repos/VeloUltralite/source/trunk/app/views/sessions/new.html.erb:1: , unexpected tRPAREN

old_output_buffer = output_buffer;;@output_buffer = '';  __in_erb_template=true ; @output_buffer.concat(( render :partial => '/shared/panel', :locals => {:title => "Welcome"} do ).to_s)
on line #1 of app/views/sessions/new.html.erb:
1: <%= render :partial => '/shared/panel', :locals => {:title => "Welcome"} do -%>
...

所以它显然不喜欢带有块的=,但如果我删除它,它就不会输出任何东西。

有谁知道如何做我想要在这里实现的目标?我想在我网站的很多地方重复使用这个面板 html。

【问题讨论】:

  • 接受的答案是正确的,但由于 Rails 5.0.0 没有layout-workaround,这是可能的,请参阅guides.rubyonrails.org/…

标签: ruby-on-rails render partial block


【解决方案1】:

虽然上述两个答案都有效(以及 tony 链接到的示例),但我最终在上面的帖子中找到了最简洁的答案(Kornelis Sietsma 评论)

我猜 render :layout 确实正是我正在寻找的东西:

# Some View
<%= render :layout => '/shared/panel', :locals => {:title => 'some title'} do %>
  <p>Here is some content</p>
<% end %>

结合:

# /shared/_panel.html.erb
<div class="v-panel">
  <div class="v-panel-tr"></div>
  <h3><%= title -%></h3>
  <div class="v-panel-c">
    <%= yield %>
  </div>
</div>

【讨论】:

  • 在 Rails 3.2.2 中,我认为你必须使用 &lt;%= %&gt; 而不是 &lt;% %&gt;,例如&lt;%= render :layout =&gt; '/shared/panel',
  • 你是对的,这篇文章对 Rails 版本没有任何假设,我相信人们可以弄清楚这一点。
  • 喜欢这个(解决了我的问题,所以+1),但这是一个好习惯吗?不会因为某种原因而减速吗?也许数据库触发的时间比预期的要早,因为另一个产量(现在没有时间自己调查,只是想知道)
  • 有什么方法可以知道内容是否已生成?如果是可选的。
  • 在 Rails 5.0 中有一个change,所以这对所有部分都是通用的,而不仅仅是布局。您可以将调用代码的第一行更改为:&lt;%= render '/shared/panel', title: 'some title' do %&gt;
【解决方案2】:

这是基于先前答案的替代方案。

shared/_modal.html.erb 上创建您的部分:

<div class="ui modal form">
  <i class="close icon"></i>
  <div class="header">
    <%= heading %>
  </div>
  <div class="content">
    <%= capture(&block) %>
  </div>
  <div class="actions">
    <div class="ui negative button">Cancel</div>
    <div class="ui positive button">Ok</div>
  </div>
</div>

application_helper.rb 上定义您的方法:

def modal_for(heading, &block)
  render(
    partial: 'shared/modal',
    locals: { heading: heading, block: block }
  )
end

从任何角度调用它:

<%= modal_for('My Title') do |t| %>
  <p>Here is some content to be rendered inside the partial</p>
<% end %>

【讨论】:

    【解决方案3】:

    您可以使用捕获助手,甚至可以在渲染调用中内联:

    <%= render 'my_partial',
               :locals => { :title => "Some Title" },
               :captured => capture { %>
        <p>Here is some content to be rendered inside the partial</p>
    <% } %>
    

    在共享/面板中:

    <h3><%= title %></h3>
    <div class="my-outer-wrapper">
      <%= captured %>
    </div>
    

    这将产生:

    <h3>Some Title</h3>
    <div class="my-outer-wrapper">
      <p>Here is some content to be rendered inside the partial</p>
    </div>
    

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

    【讨论】:

    • 内联模式非常适合需要多个块的部分。
    【解决方案4】:

    根据接受的答案,这对我使用 Rails 4 来说效果很好。

    我们可以这样渲染一个面板:

    = render_panel('Non Compliance Reports', type: 'primary') do
      %p your content goes here!
    

    这需要一个辅助方法和一个共享视图:

    辅助方法(ui_helper.rb)

    def render_panel(heading, options = {}, &block)
      options.reverse_merge!(type: 'default')
      options[:panel_classes] = ["panel-#{options[:type]}"]
    
      render layout: '/ui/panel', locals: { heading: heading, options: options } do
        capture(&block)
      end
    end
    

    查看(/ui/panel.html.haml)

    .panel{ class: options[:panel_classes] }
      .panel-heading= heading
      .panel-body
        = yield
    

    【讨论】:

    • 这也适用于 Rails 5.x,我只需要将 panel.html.haml 更改为 _panel.html.haml
    【解决方案5】:

    如果你先将它分配给一个变量然后输出它,我认为它会起作用(只是做了快速的脏测试)。

    <% foo = render :partial => '/shared/panel', :locals =>{:title => "Some Title"} do %>
    <p>Here is some content to be rendered inside the panel</p>
    <% end %>
    <%= foo %>
    

    【讨论】:

      猜你喜欢
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 2017-05-07
      • 1970-01-01
      相关资源
      最近更新 更多