RailsでWebページを作るAction Viewについて学んでみた

2015年6月10日(水)
野田 貴子

はじめに

このコラムは、Ruby初心者の著書が、Railsガイド(http://railsguides.jp/)に沿って、リアルタイムで勉強をしていくコラムです。全12回を予定しています。勉強する上でつまずいた点やその回避法、他のプログラミング言語や職業経験に基づいたアドバイスなども紹介する予定です。RubyやRailsに興味のある方は、ぜひ一緒に勉強してみませんか。

今回参照するガイドはこちらです。

Action View の概要

http://railsguides.jp/action_view_overview.html

レイアウトとレンダリング

http://railsguides.jp/layouts_and_rendering.html

Action View フォームヘルパー

http://railsguides.jp/form_helpers.html

Action View の概要

ERBについて

RailsチュートリアルでもテンプレートにはERB(文書埋め込みRubyスクリプト)を使用しているので、まずはERBに慣れたいですね。アクションファイルやモデルファイルに書くものはRubyのコードでしたが、ビューファイルに書くものはテキストです。HTML用のファイルであれば、HTMLコードを書いていきます。ただしHTMLの中にRubyのコードを埋め込む必要性は多々あるので(ユーザーから受け取ったデータを出力するなど)、その際にはRubyのコードを「」で囲んで利用します。

以下は、Rubyのコードを埋め込む方法についてまとめたものです。Railsガイドで紹介されていないものは、ドキュメントで調べました。

コード「xxx」を実行します。出力はしません。

コード内で出力関数の「puts」を使っても、出力はされません。

コード出力
#なし

コード「xxx」を実行し、結果を出力します。「%>」という文字を出力したければ、閉じかっこの「%>」と間違われないようにするため、「%\>」とエスケープをする必要があります。

コード出力
3
" %>

コード「xxx」を実行し、結果をエスケープせずに出力します。

コード出力ブラウザ上の表示
注目!" %><b>注目!</b>注目!
注目!" %>注目!注目! #太字です

「xxx」はRubyのコメントになり、出力されません。

コード出力
#なし
複数行のコメントもOK
%>
#なし

行頭までの空白を削除します。

後方の空白・改行を取り除きます。

コード出力ブラウザ上の表示

\(^∀^)
(・∀・)/
\(^∀^)
(・∀・)/ \(^∀^)

\(^∀^)
(・∀・)/\(^∀^)(・∀・)/\(^∀^)

行頭の空白と、後方の空白・改行を取り除きます。

「」は使用できますが、「」は使用できません。これらの空白除去は、テンプレートにコメント、if文、for文をはさんだり、

タグを利用したりする際、空白のせいで表示がずれてしまった場合などに使えます。</p>
<p>以上の文法をまとめると、このようになります。</p>

<p class="caption">ERBタグの種類と機能の差</p>
<table>
<tr><th>タグ</th><th>コードの実行</th><th>出力</th><th>前方空白削除</th><th>後方改行削除</th></tr>
<tr><td><% ... %></td><td>あり</td><td>なし</td><td>なし</td><td>なし</td></tr>
<tr><td><%= ... %></td><td>あり</td><td>あり(エスケープあり)</td><td>なし</td><td>なし</td></tr>
<tr><td><%== ... %></td><td>あり</td><td>あり(エスケープなし)</td><td>なし</td><td>なし</td></tr>
<tr><td><%# ... %></td><td>なし</td><td>なし</td><td>なし</td><td>なし</td></tr>
<tr><td><%- ... %></td><td>あり</td><td>なし</td><td>あり</td><td>なし</td></tr>
<tr><td><% ... -%></td><td>あり</td><td>なし</td><td>なし</td><td>あり</td></tr>
<tr><td><%= ... -%></td><td>あり</td><td>あり(エスケープあり)</td><td>なし</td><td>あり</td></tr>
<tr><td><%== ... -%></td><td>あり</td><td>あり(エスケープなし)</td><td>なし</td><td>あり</td></tr>
<tr><td><%- ... -%></td><td>あり</td><td>なし</td><td>あり</td><td>あり</td></tr>
</table>

<h2><a id="h1-3"></a>パーシャルの命名ルールについて</h2>
<p>テンプレートファイルから別のテンプレートファイル(パーシャル)を読み込む方法ですね。複数のページに共通する部分などを抜き出してパーシャルを作成しておくと、その共通部分に変更があった場合でも、修正が一ヶ所で済むのでとても便利です。</p>
<p>次のコードはすべて同じファイルを呼び出します。</p>
<div class="caption-code">
<p class="caption">#/path/to/app/views/static_pages/about.html.erb</p>
<pre class="brush:xml;" type="syntaxhighlighter"><%= render "footer" %>
<%= render " footer.html.erb" %>
<%= render "static_pages/footer " %>
<%= render partial: " footer " %>
<%= render partial: "static_pages/footer " %>
<%= render "static_pages/footer.html.erb" %>
<%= render file: "/path/to/app/views/static_pages/_footer " %>
<%= render file: "/path/to/app/views/static_pages/_footer.html.erb" %>

asとobjectオプション

テンプレートファイルから別のテンプレートファイルを呼び出す際に、データを渡したいことはよくあります。その場合の手法ですね。

例として、以下のテンプレートファイルを用意します。何かの名前を入力するフォームですね。この場合、引き渡しに必要なデータは「item」という名前のオブジェクト(name属性を持っている)です。

#_form.html.erb

<%= form_for(item) do |f| %>
  <p>
    <b>名前</b><br>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>

それではこのformパーシャルを呼び出してみましょう。最初は失敗するパターンから書いていきます。

#new.html.erb(@item = Item.first() というデータがあるとします)

<h1>新規作成ページ</h1>
<%= render partial: "form" %>

これは以下の呼び出し方と同じです。

<%= render partial: "form", locals: {form: @form} %>

しかしこれでは、formパーシャルにitemというデータが渡ってきません。代わりにformというデータ(中身は@form)が渡されます。少し書き直してみましょう。

<%= render partial: "form", as: "item" %>

これは以下の呼び出し方と同じです。

<%= render partial: "form", locals: {item: @form} %>

formパーシャルにitem変数が渡されるようになりましたが、中身のデータがありません。さらに書き直してみましょう。

<%= render partial: "form", as: "item", object: @item %>

これは以下の呼び出し方と同じです。

<%= render partial: "form", locals: {item: @item} %>

これでやっと、@itemデータが入ったitem変数をformパーシャルに渡すことができました。

まとめるとこのようになります。

データの受け渡しを指定した、パーシャルの呼び出し方

<%= render partial: "AAA", locals: {BBB: @CCC} %>
<%= render partial: "AAA", as: "BBB", object: @CCC %>

省略形

<%= render partial: "AAA" %>
<%= render partial: "AAA", as: "BBB" %>
<%= render partial: "AAA", object: @CCC %>

コレクションを出力する

同じテンプレートを繰り返し使いたいこともありますよね。たとえば、会社概要画面で新商品一覧情報を表示する際などです。その場合、それぞれの商品紹介のデザインを同じにするため、パーシャルを利用します。

例として、Productモデルから検索した商品の一覧を表示してみます。

@products = Product.find(今年の商品を検索する)

案1:パーシャルの中でループを回し、ループ内で情報を出力する

#about.html.erb

<% render "products", locals: { products: products } %>

#_products.html.erb

<% @products.each do |product| %>
  <h3><%= product.name %></h3>
  <p><%= product.price %></p>
<% end %>

どうでしょう。もっといい書き方はあるでしょうか。

案2:呼び出し元テンプレートの側でループを回し、ループ内でパーシャルを呼び出す

#about.html.erb

<% @products.each do |product| %>
  <%= render partial: "product", locals: { product: product } %>
<% end %>

#_product.html.erb

<h3><%= product.name %></h3>
<p><%= product.price %></p>

この書き方は、案1よりもパーシャルの再利用をしやすいような気がします。

案3:ループを書かずに、コレクションを使う

#about.html.erb

<% render partial: "product", collection: @products %>

#_product.html.erb

<h3><%= product.name %></h3>
<p><%= product.price %></p>

案2と同じ処理内容ですが、ループの部分を「collection」を使って表しています。パーシャルで使用している「product」という変数はパーシャルファイル名の「_product.html.erb」を元に決められます。パーシャルに渡すデータが「@products」でも「@items」でも、「product」という名が使われます。

また、パーシャルの呼び出し部分では、以下のような短縮形も使用できます。

<% render @products %>

ただしこの場合、呼び出されるパーシャルファイルは「products/_product.html.erb」に決め打ちになります。変数名が「@products」であろうと「@items」であろうと、そのインスタンスが指しているモデル(この場合はProduct)の名前を元に決められます。

1983年生まれ。大学卒業後、ソフトウェア開発の営業を経て、ソフトウェア開発業務に転向。現在は自社パッケージのフロントエンド開発のほか、PHPでの受託開発案件、日→英のローカライズ案件などを担当。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています