すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 部分テンプレートの使い方を徹底解説!

ぴっかちゃん
ぴっかちゃん

部分テンプレートとは、複数のビューファイルの中で使われている部分を一つのビューファイルとして管理する時に使います。

application.html.erbにはヘッダーやフッターなど全てのビューファイルで共通する部分を記述しました。
この他にもアプリを作成しているとサイドバーなど複数のページで共通して表示させたい部分が結構あります。
そんな時に、複数のビューファイルの共通部分として作成するのが部分テンプレートです。

部分テンプレートの使い方

この章では、部分テンプレートの使い方について解説します。

部分テンプレートを作成しよう

部分テンプレートとしてビューファイルを作成する時は_sidemenu.html.erbのようにファイル名の前に_(アンダースコア)をつける必要があります。

このようなファイル名で作成すると部分テンプレートとして使うことができます。

部分テンプレートを呼び出してみよう

それでは今作成した部分テンプレートを呼び出してみましょう。
コントローラーやビューファイルの中でビューファイルを呼び出すにはrenderメソッドを使用します。

renderメソッド

指定したテンプレートを呼び出す時に使うメソッドです。
下記のように記述します。

1
2
render 'ファイル名'    # 指定したテンプレートファイルを呼び出す
render :アクション名    # 指定したアクションのテンプレートファイルを呼び出す

renderメソッドは色々な形でビューを呼び出すことができます。
そのため「部分テンプレートを呼び出しているよ」ということを明示的にする時はオプションを使って下記のように記述することもできます。

1
render partial: 'ファイル名'

renderメソッドを記述したビューファイルと違うフォルダ内の部分テンプレートを呼び出すときは hoges/hogeのようにどのフォルダの部分テンプレートを使用しているかを記述する必要があります。

1
render partial: 'hoges/hoge'

下の例だと_right_content.html.erbはこのコードを記述しているindex.html.erbと同じフォルダにあるのでそのままファイル名を記述すれば呼び出すことができます。

_menu_html.erbはlayoutsフォルダ内にあるので、呼び出す際はlayouts/menuと記述する必要があります。

部分テンプレート呼び出し

partialオプション

partialオプションは部分テンプレートを呼び出す時に使います。
「呼び出しているのは部分テンプレートだよ」と強調したいだけなので、つけなくても構いません。

ですがlocalsオプションを使用した時はつけないとエラーが出ます。

localsオプション

localsオプションを使うと部分テンプレート内で使う変数の定義をすることができます。
例えば部分テンプレート内で変数を使いたい場合、どこかで変数を定義する必要がありますね。
そんな時にはlocalsオプションを使って変数を定義します。

ビューファイル
1
2
3
4
5
6
<%= render partial: 'ファイル名', locals: { '部分テンプレート内で使う変数': '変数に入れる値' } %>
<!--例 テンプレート内の「hoge」という変数に「こんにちは」が代入される -->
<%= render partial: 'hoge', locals: { hoge: 'こんにちは' } %>

<!-- 例 テンプレート内の「hoge」という変数に呼び出し元で定義した変数「hoge」が代入される-->
<%= render partial: 'hoge', locals: { hoge: hoge } %>

前述したとおりlocalsオプションを使った場合はpartialは省略できません。
partialを省略して書きたければ下記のように必ずlocalsオプションも省略しないといけないので注意しましょう。

1
2
3
4
<%= render 'hoge', hoge: hoge %>

<!-- localsオプションを記述しているとエラー -->
<%= render 'hoge', locals: { hoge: hoge } => エラーが発生 %>

変数を複数定義してみよう

localsオプションでは部分テンプレート内で使用する変数を複数定義することができます。
例をみてみましょう。

ビューファイル
1
<%= render partial: 'hoge', locals: { name: "山田", adrress: "東京都渋谷区", age: 20 } %>

上の例だと部分テンプレート内で使用するnameadrressageという3つの変数を定義しています。
実際に部分テンプレート内で使用してみます。

ビューファイル
1
2
3
<p>私の名前は<%= name %>です。</p>
<p>私は<%= address %>に住んでます。</p>
<p>私は<%= age %>です。</p>

このように記述すると下のように表示されます。

私の名前は山田です。

このように部分テンプレートで使用する変数は複数定義することもできます。

記述例を見てみよう

それでは実際部分テンプレートをどのように使うのか確認してみましょう。
今回はnewアクションとeditアクションで使うビューを例にしてみます。

コントローラー -->
1
2
3
4
5
6
7
def new
  @article = Article.new
end

def edit
  @article = Article.find(params[:id])
end
new.html.erb
1
2
3
4
5
6
7
8
9
<%= form_for @article do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.label :title %>
  <%= f.text_field :title %>
  <%= f.label :body %>
  <%= f.text_area :body %>
  <%= f.submit %>
<% end %>
edit.html.erb
1
2
3
4
5
6
7
8
9
<%= form_for @article do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.label :title %>
  <%= f.text_field :title %>
  <%= f.label :body %>
  <%= f.text_area :body %>
  <%= f.submit %>
<% end %>

投稿フォームと編集フォームはform_forというヘルパーメソッドを使っているため、全く同じコードで書くことができます。
ですのでここは部分テンプレートとして置き換えられそうですね。

共通する部分を_form.html.erbという名前のファイルを作成し記述します。
今回はローカル変数として変数を定義するので@articleからarticleに変えておきます。

※インスタンス変数だと使われる範囲が部分テンプレートの中だけに限定することができないため

_form.html.erb
1
2
3
4
5
6
7
8
9
<%= form_for article do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.label :title %>
  <%= f.text_field :title %>
  <%= f.label :body %>
  <%= f.text_area :body %>
  <%= f.submit %>
<% end %>

そしてnew.html.erbedit.html.erbを下記のように編集します。

new.html.erb、edit.html.erb
1
<%= render partial: 'form', locals: { article: @article } %>

partial:の部分は部分テンプレート名を記述するのでした。
部分テンプレート名は_formとアンダーバーが付いていますが、呼び出す際は_は付けません。

また今回は部分テンプレート内でarticleという変数を使っているのでlocals: { article: @article }と指定します。

左のarticleの部分は部分テンプレート内で使うときの変数名を記述します。
今回作成した部分テンプレート_form.html.erbの中ではarticleという変数を使っているのでarticleと指定しています。

右の@articleの部分はコントローラーやビューで定義した変数名を記述します。
今回はコントローラーのnewアクションとeditアクションで定義した@articleを指定しています。

new.html

上のコードが下の1行のコードになりました。

renderメソッドを使った時

もちろんnew.html.erbだけでなくedit.html.erbも1行で書くことができます。

edit.html

このように共通している全てのファイルで部分テンプレートを呼び出す記述に置き換えることができます。

手元に置いておきたい1冊

こちらの「プロを目指す人のためのRuby入門」は、Rubyの特徴から例外処理、デバック技法など実務で必要となる知識を一通り学ぶことができます。

豊富なサンプルコードと丁寧な解説でしっかり理解できるように書かれている良書です。

Ruby on Railsは、Rubyで書かれたフレームワークです。Railsで使用される構文はRubyの構文が大半です。そのためRubyをしっかり学習することでRailsへの理解が深まります。

Rubyは触りだけでRailsの扱い方に学習時間を費やす、もしくはRailsから学習している方もいますが、いずれにしても並行してRubyを学ぶと良いでしょう。

手を動かしながらRubyを学べる丁寧な技術書です!

プロを目指す人のためのRuby入門
プロを目指す人のためのRuby入門

言語仕様からテスト駆動開発・デバッグ技法まで

他のオプションを確認してみよう

renderメソッドには他にもオプションが用意されています。
例えば下記のようなコードがあったとします。

1
2
3
4
5
<% @hoges.each do |hoge| %>
  <%= hoge.name %>
  <%= hoge.title %> 
  <%= hoge.body %>
<% end %>

このコードが何箇所でも使われているので下記のような部分テンプレートを作成したとします。

_hoge.html.erb

hoge.html.erb

この部分テンプレートを使用するので下記のようにビューファイルを編集します。

ビューファイル
1
2
3
<% @hoges.each do |hoge| %>
  <%= render partial: 'hoge', hoge: hoge %>
<% end %>

上のコードは@hogesの要素の分だけ部分テンプレートが繰り返し呼び出されて表示されます。

この3行のコードをcollectionオプションを使うと下記のように1行で記述することができます。

ビューファイル
1
<%= render partial: 'hoge', collection: @hoges %>

collectionオプション

collectionオプションを使用するとcollectionオプションに指定した変数の要素の分だけ部分テンプレートが繰り返し表示されます。

ビューファイル
1
<%= render partial: 'hoge', collection: 繰り返し表示する要素が入っているインスタンス %>

先ほどの例だと@hogesにはhogesテーブルから繰り返して表示させたいレコードを取得して代入してあります。

そうすると自動で一つ一つの要素が取り出され部分テンプレートに渡されて繰り返し表示されるという流れになります。

またcollectionオプションを使用する時はpartial:を記述しないとエラーになるので気をつけましょう。

部分テンプレート内で使う変数を変更する場合

collectionオプションを使用した場合、部分テンプレート内で使用する変数はpartialで指定した名前になります。
もし別の名前として変数を使いたい場合は下記のように記述します。

ビューファイル
1
<%= render partial: 'hoge', collection: @hoges, as: "fuga" %>

この時、@hogesに入っている要素が一つずつ取り出され、部分テンプレート内の変数fugaに代入されます。

asオプション

このように記述すると@hogesの要素が一つずつfugaという変数に代入され、部分テンプレート内で使用することができます。

パフォーマンスに注意しよう

繰り返し部分テンプレートを使う場合、each文の中に記述するかcollectionオプションを使うか2つの方法があるということがわかりました。

どちらを使っても問題なく表示されるのですが、決定的な違いがあります。
それはパフォーマンスの問題です。

collectionオプションを使用して記述すると部分テンプレートが呼び出されるのは1回のみなので、eachで表示するよりもパフォーマンスが良くなります。

では実際どれくらいの違いがあるのでしょうか?
2つの例で確認してみましょう。

1000回の呼び出し

上の例では1000回部分テンプレートを呼び出しました。
確認すると呼び出すのに合計で2945.8msかかっているのがわかります。

下の例はcollectionオプションを使った時の結果です。

collectionオプション

collectionオプションを使うと1回しか読み込まれないので136.7msしかかかっていません。
1,000回呼び出すことはまずないと思いますが、これだけの差になってしまいます。
ですので部分テンプレートを繰り返し呼び出す時は出来るだけcollectionオプションを使う記述にしましょう。

省略した書き方

ビューファイル
1
<%= render partial: 'hoge', collection: @hoges %>

上のコードは下の3つの条件を全て満たしている時、このコードを省略して書くことができます。

  • 呼び出す部分テンプレートがviewsフォルダ内にあるhogesフォルダに存在する
  • 部分テンプレート名が_hoge.html.erbである
  • 部分テンプレート内で使う変数がhogeである

上の条件を全て満たしていると下記のように省略できます。

ビューファイル
1
<%= render @hoges %>

このようにだいぶ短く書くことができます。
このコードは下のコードと全く同じ結果になります。

ビューファイル
1
2
3
4
5
6
7
<!--下のコードと全く同じ -->
<%= render partial: 'hoge', collection: @hoges %>

<!--もしくは下のコードと全く同じ -->
<% @hoges.each do |hoge| %>
  <%= render partial: 'hoge', hoge: hoge %>
<% end %>

この場合、viewsフォルダのhogesフォルダ内にある部分テンプレート_hoge.html.erbを自動で選択してくれます。
かなり簡潔に書くことができますね!

部分テンプレートを使うメリット

部分テンプレートを使った時と使わない時ではビューの表示は全く変わりません。
それではなぜ部分テンプレートを使うのでしょうか?
部分テンプレートを使うメリットをいくつかあげてみます。

  • 複数箇所で使われているコードに対し、同じ記述を書かなくてすむ
  • main_content, footerのように命名規則でどの部分の記述をしてるかコードを見なくてもわかる
  • 一つのファイルにコードを書き過ぎることがなくなり可読性が上がる

それではメリットを一つずつ確認していきましょう。

同じ記述を書かなくてすむ

例えばフォームに入力してもらう内容を変えたい場合、ファイルを編集する必要がありますね。

部分テンプレートを使う前だとnew.html.erbedit.html.erbの2つのファイルを編集する必要がありました。

ですが部分テンプレートとして切り分けると部分テンプレートだけ編集すれば良いので作業効率が上がったり、修正ミスが少なくなるなどというメリットがあります。

コードをみなくても内容がわかる

部分テンプレートの名前をheadermenuなどの名前にしておくと、そのコードをみなくても「ああ、ここはヘッダーの部分なんだな」などコードの内容がとてもわかりやすくなります。

可読性が上がる

また一つのビューファイル自体が非常にコンパクトになります。
下の例を見てみましょう。

トップページ

このようなビューファイルがあった時、上のメニューと右カラムは複数のビューファイルで使われているとします。
ですので部分テンプレートを作成し、ビューを切り分けてみましょう。

切り分け後

するとこのようにビューファイルがスッキリしましたね!
長いコードになってしまうとコードが非常に読みにくくなります。
できれば一つのビューファイルは100行以内に収まるようにするのが良いでしょう。

このように部分テンプレートを使うとビューの管理がだいぶ楽になります。
重複する箇所を見つけたら部分テンプレートしてまとめておきましょう。

この記事のまとめ

  • 部分テンプレートとは、複数のビューファイルの中で使われている重複する部分を一つのビューファイルとして管理する時に使う
  • 同じ記述を書かなくて済んだり、可読性が上がるメリットがある
  • ファイル名の前に_(アンダースコア)をつける必要がある