これまでビューについてBODYタグの中に限定して話が進められてきましたが、その外側は「app/views/layouts/application.htmls.erb」で定義されています。
Railsは各テンプレートのレンダリング結果を「レイアウト」の「yield」メソッドの部分に当てはめ、またレイアウト自身をレンダリングした結果を出力としてレスポンスに乗せています。
レイアウトのテンプレートはコントローラーで以下のように変更できます。
class Admin::BaseController < ApplicationController layout 'admin' end
この「layout」メソッドの宣言により、「Admin::BaseController」のアクションとそれを継承するコントローラーのアクションでレンダリングされるレイアウトは「app/views/layouts」ディレクトリ以下の「admin.html.erb」または「admin.html.slim」が選択されます。
また、この「layout」メソッドはおなじみの「:except」や「:only」のキーにアクション名の配列を渡すことで適用するアクションを指定することもできます。
さらに個別のアクションで次のように「render」メソッドに「layout」オプションを付けることでもレイアウトを指定できます。
class Admin::BaseController < ApplicationController def index @books = Book.all render layout: "admin" end end
レイアウトの定義で使うヘルパーメソッドについて説明します。
主にHEADタグの中で使われます。
【1】stylesheet_link_tagと【2】javascript_include_tag
引数で指定したスタイルシートやJavaScriptを読み込むLINKタグ・SCRIPTタグを出力します。標準レイアウトの「app/views/layouts/application.html.erb」では以下のように呼び出されています。
<%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "application" %>
これにより「/assets/application.css」を「href」属性に持つリンクタグと「/assets/application.js」を「src」属性に持つスクリプトタグが生成されます。
【3】csrf_meta_tags
CSRF対策に使う「csrf-param」と「csrf-token」のMETAタグを生成します。
最後にビューの実装時に押さえておきたいポイントを紹介します。
N+1はビューで起こりがちなパフォーマンスに関わる問題です。ビューでモデルオブジェクトのコレクションをレコードごとに順に参照することがよくあります。
例として、BookモデルとAuthorモデルがあり、BookモデルがAuthorモデルを参照している場合を考えます。
# コントローラー @books = Book.all # ビュー - @books.each do |book| = book.title = book.author.name
このとき、ビューの最後の行でBookモデルオブジェクトが未ロードのAuthorモデルオブジェクトを呼び出しています。それによって、イテレーションのたびにデータベースへの問い合わせが発生しています。
従って、この処理だけでコントローラーでの1回と@booksの要素数N回のクエリが発生し、パフォーマンスの低下を招きます。
そこで、ActiveRecordの「includes」メソッドにより、あらかじめ関連モデルを読み込んでおくことができます。
@books = Book.includes(:author)
ビューではコレクションのイテレーションを使うことが多いため、この点には注意しましょう。
新規作成フォームと編集フォームは異なるテンプレートを使いますが、「フォームを構成するパーツは同じなので、その部分は1箇所にまとめておきたい」という場面があります。
そういう場面で有用なのが「部分テンプレート」です。例えば、「scaffold」で生成されたテンプレートでは次のような使われ方をしています。
<%= render 'form' %>
この「render」メソッドは引数に渡した「form」から同じディレクトリにある「_form.html.erb」(または「_form.html.slim」)を探し出し、レンダリングした結果を呼び出した場所に当てはめます。
また次のような呼び出し方の「locals」オプションでキーを名前、値を初期値にしたローカル変数を設定することもできます。
<%= render partial: 'form', locals: { book: @book } %>
この場合、部分テンプレート名も「partial」オプションとして指定する必要があります。
もちろん、部分テンプレートの中から呼び出し元のテンプレートに渡されたインスタンス変数を参照することもできますが、このようにローカル変数として明示的に渡して参照する方が、部分テンプレートと呼び出し元のテンプレートの関連を疎結合に保てるので、より好ましいです。
ビューはアプリケーションのインターフェースをつかさどる部分であり、多くの画面で共通のデザインを持たせるために冗長になりがちです。修正が必要になったときのために、変更する範囲を小さくとどめておく努力が日常的に求められます。
そこで、Slimや今回紹介できなかった「simple_form」といった便利な技術を積極的に使ってみてください。きっと開発が楽になることでしょう。
林 慶(Rails技術者認定シルバー試験問題作成者)
平成2年大阪生まれ。2006年から高専で情報工学を学んでいたが当時は所謂プログラミングができない工学生だった。卒業後、高専の専攻科に上がったもののマンネリ化したキャンパスライフに飽きたため休学して渡豪。そこでプログラミングに対するコンプレックスを克服するためにRuby on Railsなどでアプリケーションを作ることを覚える。
帰国後から現在までは復学し推薦システムに関する研究を行いながら、アジャイルウェアでRuby on Railsアプリケーションの開発業務に従事している。
好きなメソッドはinject。
山根 剛司(Ruby業務開発歴7年)
兵庫県生まれ。1997年からベンチャー系のパッケージベンダーで10年間勤務。当時、使用していた言語はJavaとサーバーサイドJavaScript。
2007年よりITコンサル会社に転職し、Rubyと出会って衝撃を受ける。基幹システムをRuby on Railsで置き換えるプロジェクトに従事。それ以来Ruby一筋で、Ruby on Railsのプラグインやgemも開発。
2013年より、株式会社アジャイルウェアに所属。アジャイルな手法で、Ruby on Railsを使って企業向けシステムを構築する業務に従事。
Ruby関西所属。好きなメソッドはtap。
Twitter:@spring_kuma、Facebook:山根 剛司
Copyright © ITmedia, Inc. All Rights Reserved.