書籍転載:Ruby on Rails 4アプリケーションプログラミング

書籍転載:Ruby on Rails 4アプリケーションプログラミング

ビューの基本

2014年5月7日

Railsプログラミングの最大の特徴は「MVC」。Controllerの次はViewの基本をマスターしよう。そこで使われる「ERBテンプレート」とは?

  • このエントリーをはてなブックマークに追加

書籍転載について

 本コーナーは、技術評論社発行の書籍『Ruby on Rails 4アプリケーションプログラミング』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。

 『Ruby on Rails 4アプリケーションプログラミング』の詳細や購入は技術評論社のサイト目次ページをご覧ください。

ご注意

本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。

 前回は「2.2 コントローラの基本」を説明しました。本稿はその続きです。Railsアプリケーションの作成方法については、第1回から順にお読みください。

2.3 ビューの基本

 2.2節の例では説明の便宜上、コントローラから出力を直接生成しましたが、Model - View - Controllerの考え方からすると、これはあるべき姿ではありません。最終的な出力には、ERB(Embedded Ruby)テンプレートを利用するのが基本です。

 ERBテンプレートは、一言で言うならば、HTML*14にRubyスクリプトを埋め込む(embed)ためのしくみです(図2-8)。HTMLがベースにあるため、最終的な出力をイメージしながら開発を進められるというメリットがあります。

図2-8 ERBテンプレート
  • *14 厳密にはHTMLでなくても構いません。プレーンテキストやXMLなど、テキスト形式で表現できるフォーマットであれば、なんにでも適用できるのがERBの良いところです。

 その他、ERBテンプレートでは、以下のような特長があります。

  • 任意のRubyスクリプトを埋め込めるので、条件分岐や繰り返し構文などの処理も自由に記述できる*15
  • ビューヘルパー*16を利用することで、データベースから取得した値に基づいたリンクやフォーム要素などをシンプルなコードで生成できる

 Railsでは、その他にもBuilder、JBuilderのようなテンプレートエンジンを利用できますが*17、まずはERBを理解しておけば、基本的なビュー開発には十分です。

  • *15 ただし、その自由度がゆえに注意点もあります。たとえばテンプレートファイルにデータベースアクセスのコードを記述することは可能ですが、そうすべきではありません。同様に、リクエスト情報(ポストデータやセッションなど)にアクセスするコードも避けるべきです。テンプレートはあくまで結果の表示にのみ徹するべきです。
  • *16 ビュー生成のためのユーティリティメソッドのことです。Railsに標準で用意されているものの他、自分で必要なヘルパーを定義することもできます。
  • *17 6.3.2項(転載対象外です)で改めて後述します。

2.3.1 テンプレート変数の設定

 それではさっそく、具体的なサンプルを作成してみましょう。先ほどと同じく「こんにちは、世界!」というメッセージを表示するサンプルです。しかし、今度はコントローラクラスから直接に文字列を出力するのではなく、テンプレートファイルを経由して出力を生成します。

 テンプレートを利用する場合にも、まずはリクエスト処理の基点としてのコントローラクラス(アクションメソッド)を準備する必要があります。改めてコントローラクラスから作成しても構いませんが、ここでは、先ほど作成したhelloコントローラにviewアクションを追加するものとします(リスト2-3、追記部分は太字で表しています)。

Ruby
class HelloController < ApplicationController
  …中略…
  def view
    @msg = 'こんにちは、世界!'
  end
end
リスト2-3 hello_controller.rb

 アクションメソッドが行うべき処理の中でも、ほとんどのアクションで欠かすことができないのがテンプレート変数の設定です。テンプレート変数とは、テンプレートファイルに埋め込むべき値のことで、アクションメソッドとビューとでデータを受け渡しするための橋渡し役となるものです。

 プログラム側で表示に必要なデータを用意しておき、テンプレート側ではデータを埋め込む場所や表示方法などを定義する、という役割分担がView - Controllerの基本的な関係です(図2-9)。

図2-9 テンプレートの役割

 Railsでテンプレート変数の役割を担うのは、インスタンス変数です。リスト2-3の例ではインスタンス変数として@msgを設定していますが、これがそのままテンプレート上でも自由に参照できる変数となるわけです。

 viewアクションではインスタンス変数@msgひとつに文字列を設定しているだけですが、もちろん複数の変数を設定することもできますし、値には文字列だけでなく、配列や任意のオブジェクトを設定することも可能です。

2.3.2 テンプレートファイルの作成

 続いて、アクションの結果を出力するためのテンプレートファイルを作成します。テンプレートファイルを単独で作成するためのコマンドはないので、ファイルは自分で作成する必要があります*18

  • *18 ただし、アクションメソッドとまとめて作成することはできます。前述の「【NOTE】ビューの自動生成」を合わせて参照してください。

 テンプレートファイルは、/app/viewsフォルダ配下に「コントローラ名/ アクション名.html.erb」という名前で保存する必要があります。ここでは、helloコントローラのviewアクションに対応するテンプレートなので、「/hello/view.html.erb」を作成します。これによって、Railsはアクションメソッドを実行した後、対応するテンプレートを検索/実行します。

【NOTE】テンプレートファイルの指定

 「コントローラ名/ アクション名.html.erb」は、テンプレートファイルのデフォルトの検索先です。アクションメソッドで次のように指定することで、使用するテンプレートを自由に変更することもできます*19。以下はhello/special.html.erbを呼び出す例です。

Ruby
def view
  @msg = 'こんにちは、世界!'
  render 'hello/special'
end

 renderメソッドの引数は、/app/viewsフォルダからの相対パスで指定します。また、.html.erbのような拡張子は必要ありません。

  • *19 ただし、複数のアクションでテンプレートを共有する場合を除いては、あえて異なる名前のテンプレートを用意する意味はありません。対応するアクションのないテンプレートはむしろ有害である場合の方が多いので避けてください。

 では、テンプレートファイルの具体的なコードを見ていきましょう(リスト2-4)。

ERB
<div id="main">
<%= @msg %>
</div>
リスト2-4 hello/view.html.erb

 例によって、ポイントとなる部分について順番に見ていきます。

1 動的な処理は< % … % > や< % = … % > で記述する

 テンプレートに対してRubyスクリプトを埋め込むには、< % … % > や< % = … % > のようなブロックを使います。

【構文】< % … % >、< % = … % >

ERB
<% 任意のコード %>
<%= なんらかの値を返す式 %>

 < % … % > と< % = … % > はよく似ていますが、前者がただブロックの中のコードを実行するだけであるのに対して、後者は与えられた式を出力します。たとえば、以下のような例を見てみましょう。

ERB
<div><% price = 1000
result = price * 1.05 %></div> …… 1演算を行うのみ
<div>¥<%= result %></div> >   …… 2変数resultの値を表示
HTML
<div></div>
<div>¥1050.0</div>

 < % … % > で囲まれたコードは評価されるだけで結果を返しませんので、主に演算や制御構文の記述に利用します。1も演算結果が変数resultに格納されるのみで、結果(文字列)がテンプレートに挿入されることはありません。

 一方、< % = … % > では、式の評価結果をテンプレートに挿入します。よって、2では、変数resultの値が出力にも反映されます。

 テンプレートファイルの目的が画面に対してなんらかの出力を行うことであることを考えれば、条件分岐やループなどの制御命令を除けば、ほとんどは< % = … % >の形式で記述することになるでしょう。

【NOTE】空白の制御

 < % ...- % > や< % =... - % > のように、スクリプトブロックをハイフン(-)付きで閉じることで、「- % >」の後方のスペースや改行を除去することもできます。厳密なデザインを要求する場合、余計な空白によって意図せぬスペースができてしまうのを防ぐには有効な記法です。

ERB
<div id="main">
<%= @msg -%>
</div>
HTML
<div id="main">
こんにちは、世界!</div> …… 改行が取り除かれた
2 テンプレート変数は「@変数名」で参照できる

 アクションメソッドで設定したテンプレート変数(インスタンス変数)は、テンプレート側でもそのまま「@変数名」の形式で参照できます。ごく直感的な記述ですので、迷うところはないでしょう*20

  • *20 Rails 2以前では、動的な出力にはhメソッドを介するのが原則でしたが、Rails 3以降では不要になりました。詳しくは4.2.7項(転載対象外です)も参照してください。

 以上が理解できたら、さっそくサンプルを実行してみます。ブラウザから次のアドレスを指定し、図2-10のような結果が得られることを確認してください。

  http://localhost:3000/hello/view

図2-10 テンプレートファイルの内容が表示される

【NOTE】ビューの自動生成

 rails generateコマンドでは、コントローラクラス(アクションメソッド)と合わせて、テンプレートファイルを自動生成することもできます。たとえば、以下はhelloコントローラのshowアクションと、対応するテンプレートファイルhello/show.html.erbを自動生成する例です。

コマンドライン
> rails generate controller hello show

 「hello index show new」のようにすることで、複数のアクションをまとめて生成することもできます。生成すべきアクションがあらかじめわかっている場合には、このようにまとめて必要なファイル(やコード)を生成してしまう方が手軽でしょう。

【NOTE】アクションメソッドは省略可能

 テンプレート変数の設定など、アクションメソッドでの処理が必要ない場合、アクションメソッドは省略できます。たとえば、「http://localhost:3000/hello/nothing」であれば、Railsはまずhelloコントローラのnothingアクションを検索しますが*21、アクションが存在しない場合、そのままテンプレートファイルhello/nothing.html.erbを検索&実行します。

  • *21 2.2.3項のルーティング設定の場合です。

2.3.3 補足:共通レイアウトの適用

 リスト2-4の実行結果を、ブラウザの[ソースの表示]から確認してみましょう。

HTML
<!DOCTYPE html>
<html>
<head>
  <title>Railbook</title>
  <link data-turbolinks-track="true" href="/assets/application.css?body=1"
    media="all" rel="stylesheet" />
  <link data-turbolinks-track="true" href="/assets/hello.css?body=1" media="all" rel="stylesheet" />
  <script data-turbolinks-track="true" src="/assets/jquery.js?body=1"></script>
  <script data-turbolinks-track="true" src="/assets/jquery_ujs.js?body=1"></script>
  <script data-turbolinks-track="true" src="/assets/turbolinks.js?body=1"></script>
  <script data-turbolinks-track="true" src="/assets/hello.js?body=1"></script>
  <script data-turbolinks-track="true" src="/assets/application.js?body=1"></script>
  <meta content="authenticity_token" name="csrf-param" />
  <meta content="dSTDVzac0MFzW5kXSE7TZv7bH8S/ggz8PmhaLkmnQE4=" name="csrf-token" />
</head>
<body>

  <div id="main">
  こんにちは、世界!
  </div>

</body>
</html>

 テンプレートファイル(view.html.erb)で定義したものよりも随分多くのコンテンツが出力されていることが確認できます(view.html.erb以外による出力は太字で表しています)。

 これら自動で付与されているコンテンツは、実は/app/views/layouts/application.html.erbで定義されているものです*22

  • *22 application.html.erbではいくつかのビューヘルパーが利用されていますが、これらの詳細は改めて第4章(転載対象外)で後述します。
ERB
<!DOCTYPE html>
<html>
<head>
  <title>Railbook</title>
  <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

  <%= yield %> …… ここに個別のテンプレートが埋め込まれる

</body>
</html>
リスト2-5 application.html.erb

 Railsではデフォルトで、application.html.erbの「< % = yield % >」に個別のテンプレートを埋め込んだ上で、最終的な出力を生成します。application.html.erbのことをレイアウトテンプレート、あるいは単にレイアウトと呼びます(図2- 11)。

図2-11 レイアウトのしくみ

 レイアウトとは、要はサイトデザインの外枠と考えれば良いでしょう。レイアウトを利用することで、ヘッダ/フッタやサイドメニューのようなサイト共通のデザインを一箇所にまとめられますので、以下のようなメリットがあります。

  • サイトデザインを変更する場合もレイアウトだけを変更すれば良い
  • 個別のテンプレートにはページ固有のコンテンツだけを記述すれば良い
  • サイト構成(ナビゲーションなど)に一貫性ができるため、使い勝手も向上する

 開発生産性、保守性、ユーザの利便性いずれをとっても、外枠をレイアウトとして別に定義することの重要性はおわかりいただけるのではないでしょうか。

 レイアウトの詳細は改めて4.7節(転載対象外です)で解説しますので、まずはRailsではデフォルトで

  個別テンプレートにはレイアウトテンプレートが適用される

ことを覚えておいてください*23

  • *23 もしもレイアウトが自動で適用されることを望まないならば、application.html.erbを削除、またはリネームしてください。

2.3.4 補足:コメント構文

 ERBテンプレートでは、以下のようなコメント構文を利用できます。以降でもよく利用しますので、ここでよく利用する記法をまとめておきます。

1 < % # … % >

 ERB標準のコメント構文で、< % #... % > ブロック配下をすべてコメントと見なします。「%」と「#」の間に空白を挟んではいけません。

ERB
<%# コメントです。
    この行もコメント %>
2 #

 1とよく似ていますが、こちらはRuby標準のコメント構文で、< % ... % >ブロックの配下でのみ利用できます。こちらは「#」からその行末までがコメントと見なされます(単一行コメント)。

ERB
<% msg = 'これはコメントではありません。'
   # これはコメントです。 %>
3 < % if false % > … < % end % >

 条件分岐構文を利用したコメントアウトです。条件式がfalseですので、常に配下のコンテンツは無視されるというわけです。2の構文は< % … % > の配下でしか利用できませんが、3の記述を利用することで、< % … % > や< % = … % >を跨いだコンテンツをまとめてコメントアウトできます。

 デバッグ時に特定の機能やレイアウトを一時的に無効化したい場合にも利用できるでしょう。

ERB
<% if false %>
<% msg = 'この部分は無視されます。' %>
<%='これも無視されます。' %>
<% end %>
4 < % =begin % > … < % =end % >

 3の構文は確かに便利ですが、問題もあります。というのも、標準的な条件分岐構文をコメントアウトの用途に利用しているため、本来の条件分岐と一見して見分けがつきにくいことがあるのです。

 そのような場合には、< % =begin % > … < % =end % > を利用すると良いでしょう。=begin … =end は主にドキュメンテーションコメントを記述するための構文で、Rubyでも複数行コメントに利用する場合があります。3よりも明確にコメントであることを表現できるというメリットがあります。

ERB
<%
=begin
%>
<% msg = 'この部分は無視されます。' %>
<%='これも無視されます。' %>
<%
=end
%>

 4の構文では、必ず「=begin」「=end」は行頭に記述しなければならない点に注意してください。たとえば、以下のような記述はいずれも不可です。

ERB
<% =begin %>       …… 前に「< % 」がある
  …
<%
  =end>            …… 余計なスペースがある
%>
5 <!-- … -->

 標準的なHTMLのコメントです。ERBはあくまでHTMLをベースとしていますから、当然、HTMLのコメントも利用できます。ただし、14と異なり、ブラウザ側で処理されるコメントですので、配下の内容はクライアント側からも見えてしまう点に注意してください。

ERB
<!-- <%= 'ブラウザの画面上には表示されません。' %> -->

 エンドユーザが参照する可能性がある情報(サイト管理者の情報など)を記述したり、デバッグ時に出力したHTMLを確認するための目印を埋め込んだりしたい場合に便利です。

 次回は「2.4 モデルの基本」を説明します。

※以下では、本稿の前後を合わせて5回分(第3回~第7回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

3. Ruby on Rails 4アプリケーションの作成

環境が整ったら、いよいよアプリ作成を始めよう。スケルトンコードの生成から、Webサーバー上で実際にRailsアプリを動かすところまでを説明。

4. コントローラの基本

Railsプログラミングの基点は、MVCのControllerクラス。ここから具体的なコードを記述していこう。

5. 【現在、表示中】≫ ビューの基本

Railsプログラミングの最大の特徴は「MVC」。Controllerの次はViewの基本をマスターしよう。そこで使われる「ERBテンプレート」とは?

6. モデルの基本

Railsプログラミングの最大の特徴は「MVC」。ControllerとViewをマスターしたら、最後にModelの基本を習得しよう。データベースをO/Rマッパーで活用する。

7. Railsの設定情報

「第1章 イントロダクション」~「第2章 Ruby on Railsの基本」までの転載が完了。まとめて読んでRails開発を学ぼう。

サイトからのお知らせ

Twitterでつぶやこう!