如何创建子布局以从页面代码中删除重复?

时间:2013-08-17 12:24:56

标签: ruby-on-rails templates layout nested erb

我正在构建一个应用程序,其中七个页面是静态的,看起来几乎相同并共享同一个控制器,StaticPagesControllerStaticPagesController我刚刚定义了7个空行为,这些行为对应于static_pages目录中的视图。

所有静态页面都将基于一般应用程序布局(layouts/application.html.erb,由页眉和页脚组成)并且它们都将包含顶部的“英雄单元”(带有图片的大横幅)在它下面,有两列。第一列将包含每个页面上不同的文本段落,在第二列中我将呈现一组ActiveModel对象(每个页面上将显示不同的对象子集,但我想要能够只渲染一次渲染代码。)

问题

我想要实现的是是一种从layouts/application.html.erb继承页眉和页脚的布局,并允许我只编写将在每个页面之间更改的代码,并避免重复结构,英雄渲染和集合渲染。

我的(可能是错误的)解决方案

我找到了一种有效的方法,但在阅读了关于nested layouts的Rails指南后,我有点困惑,我不确定这是否是正确的方法。我是这样做的:

我使用以下代码创建了layouts/static_page.html.erb

<%= render partial: 'shared/hero', locals: { big: true, big_text: hero_big_text } %>

<div class="container">
  <div class="row">
    <div class="col-sm-6">
      <%= yield :introduction %>

      <%= render 'hook_button' %>
    </div>
    <div class="col-sm-6 bo-offers-col">
      The @collection will be rendered here
    </div>
  </div>
</div>

第一行渲染英雄将几个局部传递给它,其中一个必须在视图中定义。其余的代码创建了两列,并在第一个代码中生成introduction代码,并且应该在第二个代码中呈现@collection对象(将在控制器中定义)。

以下是其中一个观点包含的内容:

<%# Page title %>
<% provide :title, "Page title" %>

<%# Specify the content %>
<% content_for :hero, yield(:title) %>

<% content_for :introduction do %>
  <h2>Page subtitle</h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris congue fermentum quam a lacinia.</p>
  <p>Maecenas at sapien ut risus congue sodales eget quis enim. Etiam pulvinar nulla non libero lobortis vulputate. Aliquam convallis sapien nec velit sagittis molestie. Morbi porta pulvinar varius. Donec nec velit at nisi ultrices commodo viverra eu enim.</p>
<% end %>

<%# Render the stuff %>
<%= render template: 'layouts/static_page', locals: { hero_big_text: false } %>

首先,我提供了一个标题,既可以用作页面<title>,也可以用作英雄内部的文本。我使用content_for来提供第一列的内容 最后,我使用<%= render template: 'layouts/static_page', locals: { hero_big_text: false } %>渲染我之前定义的模板,传递我用来决定要显示哪种类型的英雄(在英雄部分中使用)。

此解决方案有效,但我不确定它是否在语义上正确或是否有更好的方法来执行此操作。我没有设法找到解决这个问题的任何文件或问题,我想知道是否有更好的方法来做到这一点。

1 个答案:

答案 0 :(得分:1)

我建议在这里使用部分布局来简化许多不同的content_for调用。所以从您的视图文件中执行此操作

<%= render layout: 'hero_layout', locals: { hero_big_text: false } do %>
  <h2>Page subtitle</h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris congue fermentum quam a lacinia.</p>
  <p>Maecenas at sapien ut risus congue sodales eget quis enim. Etiam pulvinar nulla</p>
<% end %>

然后使用layouts/static_page.html.erb而不是使用app/views/application/_hero_layout.html.erb创建上面代码中引用的部分布局<%= render partial: 'hero', locals: { big: true, big_text: hero_big_text } %> <div class="container"> <div class="row"> <div class="col-sm-6"> <%= yield %> <%= render 'hook_button' %> </div> <div class="col-sm-6 bo-offers-col"> The @collection will be rendered here </div> </div> </div> ,代码如下:

shared

另请注意,使用hero文件夹来显示部分内容并不是正确的方法。相反,您可以使用template inheritance。因此,/app/views/application/_hero.html.erb部分将从模板继承路径中获取。这可能意味着您需要将其设置在{{1}},但这取决于您应用的具体细节。