2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Rails][View] Layouts and Rendering in Rails 2

Posted at

3 Structuring Layouts
When Rails renders a view as a response, it does so by combining the view with the current layout, using the rules for finding the current layout that were covered earlier in this guide. Within a layout, you have access to three tools for combining different bits of output to form the overall response:

Asset tags
yield and content_for
Partials

current layoutを基本としてレスポンスをつくる。

3.1 Asset Tag Helpers
Asset tag helpers provide methods for generating HTML that link views to feeds, JavaScript, stylesheets, images, videos and audios. There are six asset tag helpers available in Rails:

auto_discovery_link_tag
javascript_include_tag
stylesheet_link_tag
image_tag
video_tag
audio_tag

You can use these tags in layouts or other views, although the auto_discovery_link_tag, javascript_include_tag, and stylesheet_link_tag, are most commonly used in the <head> section of a layout.

The asset tag helpers do not verify the existence of the assets at the specified locations; they simply assume that you know what you're doing and generate the link.

6つのうち、上3つはおもにlayoutの

で使用される。
3.2 Understanding yield
Within the context of a layout, yield identifies a section where content from the view should be inserted. The simplest way to use this is to have a single yield, into which the entire contents of the view currently being rendered is inserted:

layout内でyieldを使うと、viewの内容をそこに挿入できる。

<html>
  <head>
  </head>
  <body>
  <%= yield %>
  </body>
</html>
You can also create a layout with multiple yielding regions:

複数のyieldをもつlayoutも作れる。

<html>
  <head>
  <%= yield :head %>
  </head>
  <body>
  <%= yield %>
  </body>
</html>
The main body of the view will always render into the unnamed yield. To render content into a named yield, you use the content_for method.

viewのメイン部分はただのyieldの部分に挿入される。名前付き(:head)のyieldにviewを挿入するにはcontent_forメソッドを使う。

3.3 Using the content_for Method
The content_for method allows you to insert content into a named yield block in your layout. For example, this view would work with the layout that you just saw:
<% content_for :head do %>
  <title>A simple page</title>
<% end %>
 
<p>Hello, Rails!</p>
The result of rendering this page into the supplied layout would be this HTML:
<html>
  <head>
  <title>A simple page</title>
  </head>
  <body>
  <p>Hello, Rails!</p>
  </body>
</html>

view内でcontent_forメソッドを使用することで、layout内の名前付きyieldに要素を挿入することができる(ここではviewでcontent_forを定義して、layoutでyield :content_name するという順番)。

The content_for method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It's also useful for inserting tags that load page-specific JavaScript or css files into the header of an otherwise generic layout.

layout内にサイドバー、フッターといった要素をバラバラにもちたいときや、ページ固有のjavascript、cssをヘッダーに埋め込みたいときなどに有用。

3.4 Using Partials
Partial templates - usually just called "partials" - are another device for breaking the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.

パーシャルはテンプレートの一種である。

3.4.1 Naming Partials
To render a partial as part of a view, you use the render method within the view:
<%= render "menu" %>
This will render a file named _menu.html.erb at that point within the view being rendered. Note the leading underscore character: partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore. This holds true even when you're pulling in a partial from another folder:

パーシャルを利用するには、view内でrenderメソッドを呼び出す。パーシャルファイルの名前解決はviewファイルの位置を基準に解決される。

<%= render "shared/menu" %>
That code will pull in the partial from app/views/shared/_menu.html.erb.
3.4.2 Using Partials to Simplify Views
One way to use partials is to treat them as the equivalent of subroutines: as a way to move details out of a view so that you can grasp what's going on more easily. For example, you might have a view that looked like this:
<%= render "shared/ad_banner" %>
 
<h1>Products</h1>
 
<p>Here are a few of our fine products:</p>
...
 
<%= render "shared/footer" %>

パーシャルはサブルーチンのように扱うのがよい。

Here, the _ad_banner.html.erb and _footer.html.erb partials could contain content that is shared among many pages in your application. You don't need to see the details of these sections when you're concentrating on a particular page.

For content that is shared among all pages in your application, you can use partials directly from layouts.

このケースでは_ad_banner.html.erb と _footer.html.erbには多くのページで利用する機能をまとめるのがよい。

3.4.3 Partial Layouts
A partial can use its own layout file, just as a view can use a layout. For example, you might call a partial like this:

パーシャル内でも、layoutを利用することができる。

<%= render partial: "link_area", layout: "graybar" %>
This would look for a partial named _link_area.html.erb and render it using the layout _graybar.html.erb. Note that layouts for partials follow the same leading-underscore naming as regular partials, and are placed in the same folder with the partial that they belong to (not in the master layouts folder).

Also note that explicitly specifying :partial is required when passing additional options such as :layout.

このとき_graybar.html.erbが読み込まれて、パーシャルに適用される。パーシャル用のlayoutのファイル名はunderscoreから始める必要がある。

3.4.4 Passing Local Variables
You can also pass local variables into partials, making them even more powerful and flexible. For example, you can use this technique to reduce duplication between new and edit pages, while still keeping a bit of distinct content:

パーシャルにローカル変数を渡すことができる。

new.html.erb
<h1>New zone</h1>
<%= render partial: "form", locals: {zone: @zone} %>
edit.html.erb
<h1>Editing zone</h1>
<%= render partial: "form", locals: {zone: @zone} %>
_form.html.erb
<%= form_for(zone) do |f| %>
  <p>
    <b>Zone name</b><br/>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
Although the same partial will be rendered into both views, Action View's submit helper will return "Create Zone" for the new action and "Update Zone" for the edit action.

Every partial also has a local variable with the same name as the partial (minus the underscore). You can pass an object in to this local variable via the :object option:
<%= render partial: "customer", object: @new_customer %>
Within the customer partial, the customer variable will refer to @new_customer from the parent view.

If you have an instance of a model to render into a partial, you can use a shorthand syntax:
<%= render @customer %>
Assuming that the @customer instance variable contains an instance of the Customer model, this will use _customer.html.erb to render it and will pass the local variable customer into the partial which will refer to the @customer instance variable in the parent view.
3.4.5 Rendering Collections
Partials are very useful in rendering collections. When you pass a collection to a partial via the :collection option, the partial will be inserted once for each member in the collection:
index.html.erb
<h1>Products</h1>
<%= render partial: "product", collection: @products %>
_product.html.erb
<p>Product Name: <%= product.name %></p>
When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is _product, and within the _product partial, you can refer to product to get the instance that is being rendered.

There is also a shorthand for this. Assuming @products is a collection of product instances, you can simply write this in the index.html.erb to produce the same result:
<h1>Products</h1>
<%= render @products %>
Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection:
index.html.erb
<h1>Contacts</h1>
<%= render [customer1, employee1, customer2, employee2] %>
customers/_customer.html.erb
<p>Customer: <%= customer.name %></p>
employees/_employee.html.erb
<p>Employee: <%= employee.name %></p>
In this case, Rails will use the customer or employee partials as appropriate for each member of the collection.

In the event that the collection is empty, render will return nil, so it should be fairly simple to provide alternative content.
<h1>Products</h1>
<%= render(@products) || "There are no products available." %>
3.4.6 Local Variables
To use a custom local variable name within the partial, specify the :as option in the call to the partial:
<%= render partial: "product", collection: @products, as: :item %>
With this change, you can access an instance of the @products collection as the item local variable within the partial.

You can also pass in arbitrary local variables to any partial you are rendering with the locals: {} option:
<%= render partial: "products", collection: @products,
           as: :item, locals: {title: "Products Page"} %>
Would render a partial _products.html.erb once for each instance of product in the @products instance variable passing the instance to the partial as a local variable called item and to each partial, make the local variable title available with the value Products Page.

Rails also makes a counter variable available within a partial called by the collection, named after the member of the collection followed by _counter. For example, if you're rendering @products, within the partial you can refer to product_counter to tell you how many times the partial has been rendered. This does not work in conjunction with the as: :value option.

You can also specify a second partial to be rendered between instances of the main partial by using the :spacer_template option:

renderの :as や :locals オプションを利用することで、パーシャルに対してローカル変数を渡すことができる。

3.4.7 Spacer Templates
<%= render partial: @products, spacer_template: "product_ruler" %>
Rails will render the _product_ruler partial (with no data passed in to it) between each pair of _product partials.
3.4.8 Collection Partial Layouts
When rendering collections it is also possible to use the :layout option:

<%= render partial: "product", collection: @products, layout: "special_layout" %>
The layout will be rendered together with the partial for each item in the collection. The current object and object_counter variables will be available in the layout as well, the same way they do within the partial.
3.5 Using Nested Layouts
You may find that your application requires a layout that differs slightly from your regular application layout to support one particular controller. Rather than repeating the main layout and editing it, you can accomplish this by using nested layouts (sometimes called sub-templates). Here's an example:

Suppose you have the following ApplicationController layout:
app/views/layouts/application.html.erb
<html>
<head>
  <title><%= @page_title or "Page Title" %></title>
  <%= stylesheet_link_tag "layout" %>
  <style><%= yield :stylesheets %></style>
</head>
<body>
  <div id="top_menu">Top menu items here</div>
  <div id="menu">Menu items here</div>
  <div id="content"><%= content_for?(:content) ? yield(:content) : yield %></div>
</body>
</html>
On pages generated by NewsController, you want to hide the top menu and add a right menu:
app/views/layouts/news.html.erb
<% content_for :stylesheets do %>
  #top_menu {display: none}
  #right_menu {float: right; background-color: yellow; color: black}
<% end %>
<% content_for :content do %>
  <div id="right_menu">Right menu items here</div>
  <%= content_for?(:news_content) ? yield(:news_content) : yield %>
<% end %>
<%= render template: "layouts/application" %>
That's it. The News views will use the new layout, hiding the top menu and adding a new right menu inside the "content" div.

There are several ways of getting similar results with different sub-templating schemes using this technique. Note that there is no limit in nesting levels. One can use the ActionView::render method via render template: 'layouts/news' to base a new layout on the News layout. If you are sure you will not subtemplate the News layout, you can replace the content_for?(:news_content) ? yield(:news_content) : yield with simply yield.

NewsControllerはnews.html.erbを呼び出す。layout内でrender templateすることで、(news.html.erbをviewのようにあつかい、application.html.erbをlayoutのようにあつかうことができ)layoutのネストができる(news.html.erbでrenderしないと、news.html.erbをlayoutとして扱うことになる)。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?