Blank?=False

「呉下の阿蒙にあらず」をモットーにしたITエンジニアの日々

基礎RubyOnRails Chapter3-2 テンプレートとヘルパー

f:id:stonebeach-dakar:20160618082625p:plain

基礎RubyOnRails Chapter3-2 コントローラとビューについて書いていきます。

改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)

改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)

RailsのVIEWとは?

MVCモデルにおけるVIEWにあたるもの。(まんまやん)

こんな説明じゃあかんので、ちゃんと説明すると、見た目、Webページの見た目のデザインの定義です。

具体的な話をすると、モデルの情報をどのような形で出力するかを定義して、そのとおりに表示するHTMLを出力する、というのがVIEWの役割です。

Railsでは、Rubyソースコード(いわゆるrb)ファイルではなく、テンプレートファイル(erb)という形式で作成します。
ファイルの拡張子は.erbなのですが、決まりとして.erbの前に.htmlを付ける必要があるので、ある意味.html.erbなのかも。

テンプレートとは?

↑の説明通り、HTMLを生成するための部品です。Rails界隈ではERB,ERBテンプレート, または単にテンプレートと言われることが多いです。

テンプレートの使い方

前回の記事に書いたように、Rails設定より規約という設計哲学があるので、もちろんテンプレートにもルールがあります。
stonebeach-dakar.hatenablog.com

テンプレートファイル名は、アクション名.html.erbというのが基本的なルールになっていて、このルールに従うことで RailsControllerのアクションの処理が完了した後自動的にアクション名.html.erbという名前のテンプレートファイルを呼び出すようになっています。
ただし、このルールに従わないで別のテンプレートファイルを使いたい場合も数多くあります。

例えば、ログインに成功した後はアクションのテンプレートを呼び出すが、失敗した場合ログイン失敗を表示するためのテンプレートファイルを呼び出す、といった場合です。
そういう時には、renderというメソッドでテンプレートを指定することができます。
(具体的な使い方は下のレンダリングの項で)

テンプレートの書き方

テンプレートは基本的にはHTMLで書くことになりますが、<% %>, <%= %>というタグを使うことでタグ内部にRubyのコードを書くことができます。

<% %>, <%= %>は以下の様な機能の違いがあります。

文法 機能
<% %> <% %>の中のコードを実行。実行結果はHTMLに出力されない。
<%= %> <%= %>の中のコードを実行。実行結果はHTMLに文字列として出力される。


この2つの使い分けは、

  • <% %>はif,Each,end,変数の代入など、画面に表示しない処理を書くときに使う。
  • <%= %>はコントローラで準備したデータの内容や、フラッシュメッセージの表示で使う。

という感じです。

つまり、<% %>は野村克也、<%= %>は長嶋、王ってわけです。
(野球ネタですみません。腹を切って謝罪しません。)

コントローラからテンプレートへの値渡し

基本的に、テンプレートでデータを作ると言うのはありません。データはすべてコントローラが準備して上げる必要があります。
例えば、インデックスページを表示する場合、コントローラでモデルのデータを変数に格納し、それをテンプレートに渡すことになります。
データの受け渡しはインスタンス変数を使います。
実装としては、以下の様な形になります。
(てきとうに書いたから細かいツッコミしないでね!)

SampleController.rb

def index
  @data = Data
end

index.html.erb

<table>
  <% @data.each do |d| %>
  <tr>
   <td><%= d.name %></td>
   <td><%= d.code %></td>
  </tr>
 <% end %>
</table>

コントローラのindexアクションで@dataというインスタンス変数にデータを格納して、それをテンプレートで使う、という感じです。

テンプレート内の条件分岐

テンプレート内で、例えばデータの中身が空だったら別の表示をする、といったシチュエーションは数多く有ります。
そういう時はRubyで開発する時と同様、Ifで条件分岐すれば、実現できます。
以下のサンプルの場合、@dataのnameが空だったら名前をくださいと表示します。
コレの応用で、ログインしている場合はユーザー名の表示、ログインしていない場合はログインページのリンク表示、等ができます。

<% if @name %>
<%= "名前は{@name}です。" %>
<% else %>
  <%= "名前をください "%>
<% end %>

テンプレート内の繰り返し

大量のデータを表示するインデックスページなどは、データを出力するタグをいちいち全部書いていくのは大変です。
というか、めんどくさくてやりたくありませんよね。

<%= "氏名:#{Users(1).name}"  %>
<%= "住所:#{Users(1).address}"  %>
<%= "電話番号:#{Users(1).phonenumber}"  %>
<%= "性別:#{Users(1).sex}"  %>
<%= "氏名:#{Users(2).name}"  %>
<%= "住所:#{Users(2).address}"  %>
<%= "電話番号:#{Users(2).phonenumber}"  %>
<%= "性別:#{Users(2).sex}"  %>
<%= "氏名:#{Users(3).name}"  %>
<%= "住所:#{Users(3).address}"  %>
<%= "電話番号:#{Users(2).phonenumber}"  %>
<%= "性別:#{Users(3).sex}"  %>
<省略> 

こういうコードはコピペしがち。そしてミスしがち。(↑のサンプルもミスってます)。おまけにごちゃごちゃしていて読む気わかない。
そしてメンテナンス性も良くないので、例えば「おーい◯◯くん、お客さんが性別は表示しなくてもいいってー。直しといてね」なんて言われた日には性別の行だけを探していちいち削除しなくてはいけません。めんどくさ〜!

こういう同じものが繰り返されるものは、Rubyでの開発と同様繰り返し構文を使ってササッとスマートにエレガントなコードにしましょう。

<%= Users.each do |user| %>
  <%= "氏名:#{user.name}" %>
  <%= "住所:#{user.address}" %>
  <%= "電話番号:#{user.phonenumber}" %>
  <%= "性別:#{user.sex}" %>
<% end %>

こうすることで、「おい◯◯君!性別を表示しないでくれってお客さんに言われた!10分で直してくれ!」なんて無茶な依頼が来てもささっと直せることでしょう。
(決して自分の実体験ではない)

上のような重複がないコードになることでDRY原則を守ることができます。

ちなみに、こういったソースコードを改善し、読みやすくメンテナンスしやすいコードにすることをリファクタリングと言います。
プライベートのコードはそこまで気にしなくてもいいですが(と言っても汚いとメンテナンスしにくいよ)、仕事としてプログラミングをするなら、常にリファクタリングすることを心がけることでメンテナンス性・品質の維持ができ、スムーズな開発ができると思います。

リファクタリングの名書がありますので、興味を持ったら読んでみるのをオススメします。(分厚いので時間かかるよ〜)
言語はJavaですが、Java特有の機能などは使っていないので、他言語ができればだいたい読めます。

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

ちなみに、Rubyエディションというのもあります。こちらは読んだことがありません。

リファクタリング:Rubyエディション

リファクタリング:Rubyエディション


レンダリング

定義したテンプレートを実際のHTMLに出力することをレンダリングといいます。
このレンダリングの際に、ActionView::Baseというクラスを継承し、ヘルパーモジュールをMixinしたクラスが自動的に生成され、そのインスタンスがテンプレートを実行してHTMLコードを出力します。

ヘルパーメソッドとは?

ヘルパーメソッドとは、テンプレートで使用できるヘルパー的な機能や、汎用的な機能をまとめたメソッドで、レンダリングの際に特定のHTMLタグ、文字列として出力されます。
ActionViewで提供されているものが多いですが、必要な機能がなければ自作することもできます、
例えば、link_toというヘルパーは、レンダリングすると<a href="">というハイパーリンクタグを生成します。

どのヘルパーがどのようなHTMLを作るか、というのはリファレンスを見るのもいいですが、実際に使ってみて、ブラウザのソース表示からHTMLを見るのがてっとり早く機能がわかります。

ヘルパーメソッドの例

以下のようなヘルパーメソッドがあります。

メソッド名 機能
simple_format <p></p>で囲み、改行を<br/>にする
truncate 文字列を指定の文字数に省略する。
higihlight 文字列の中の語句を<strong class="highlight"></strong>で囲む
image_tag <img>タグを生成する。画像のサイズ、alt,位置などの調整が可能
form_tag HTMLフォーム(labelタグ、inputタグ,submitタグ等)を作成する

それぞれのヘルパーを使ってみたいと思ったらぐぐってみてください。(そのうち自分でも書きます)

自作ヘルパーメソッド

ヘルパーメソッドは自作することもできます。
自作する場合、汎用的なヘルパーメソッドはapp/helpersディレクトリ内の application_helper.rbに記述し、 似た機能が幾つかまとめてモジュールとしたい場合、helpersディレクトリ内に◯◯_helper.rbというファイル名を作ってそこに書くのがベストです。

ここで注意する点は、すべてのヘルパーがすべてのテンプレートにMixinされるということです。
つまり、名前の衝突が発生する可能性があります。

本書では、ヘルパーメソッド名は衝突することがないよう気をつける必要がある、と警告されています。