基礎RubyOnRails Chapter3-2 テンプレートとヘルパー
基礎RubyOnRails Chapter3-2 コントローラとビューについて書いていきます。
改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)
- 作者: 黒田努,佐藤和人,株式会社オイアクス
- 出版社/メーカー: インプレス
- 発売日: 2015/05/22
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
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
というのが基本的なルールになっていて、このルールに従うことで
RailsはController
のアクションの処理が完了した後自動的にアクション名.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)
- 作者: Martin Fowler,児玉公信,友野晶夫,平澤章,梅澤真史
- 出版社/メーカー: オーム社
- 発売日: 2014/07/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (10件) を見る
ちなみに、Rubyエディションというのもあります。こちらは読んだことがありません。
- 作者: Jay Fields,Shane Harvie,Martin Fowler,Kent Beck,長尾高弘
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2010/02/27
- メディア: 大型本
- 購入: 9人 クリック: 321回
- この商品を含むブログ (50件) を見る
レンダリング
定義したテンプレートを実際の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される
ということです。
つまり、名前の衝突が発生する可能性があります。
本書では、ヘルパーメソッド名は衝突することがないよう気をつける必要がある、と警告されています。