部分テンプレートの作成とrenderの使い方
ビューファイルを書いていると記述量がどんどん増えてきて、繰り返しの部分も出てくるかと思います。そんな時に役立つ部分テンプレートのお話です。DRYってやつですね。
部分テンプレートとは
ビューファイルの中で何度も出てくる同じ記述を切り出して、別のファイルに用意しておきます。そしてメインのビューファイルではその別ファイルを呼び出して使うことで、同じ記述を繰り返すことを避けようというものです。
乱暴な言い方をすれば変数と同じような考え方ですね。変数に値を入れて何度も使うように、部分テンプレートにビューの一部を記述しておいて何度も使いまわそうという感じ。
部分テンプレートの使い方
ビューファイルから省略したい部分の記述を切り取ります。
_xx.html.erb
というファイルを作成し、切り出した記述を貼り付けます。
(同じフォルダ内でも別フォルダでも構いません)
ビューファイルの切り出した部分で、renderメソッドを使って部分テンプレートを呼び出します。
この時、:localsオプションを使って変数を与えると、部分テンプレート内で使用することができます。
例えばapp/views/posts/index.html.erb
というファイルの一部を切り出してapp/views/posts/_post.html.erb
というファイルを作ったとすると、以下のように書きます。
<%= render partial: "post", locals: { post: @post } %>
partial: "post"
では_post.html.erbというファイルを呼び出しています。もし同じフォルダではなく別のフォルダ内に部分テンプレートを作成していた場合、partial: "shared/post"
のようにファイルの場所を指定する必要があります。
locals: { post: @post }
は、index.html.erb内の@postという変数を、部分テンプレートの_post.html.erb内でpostという変数として使用するための記述です。
部分テンプレートの繰り返し
localsの代わりにcollectionオプションを使って変数を与えると、その変数内の要素一つひとつに対して部分テンプレートを繰り返すことができます。
書き方はこうなります。
<%= render partial: "post", collection: @posts %>
これで、@postsに入っている要素を一つずつ取り出して、部分テンプレートを繰り返し表示します。
やっていることは下の記述と同じだと思います。こんなふうにeachを使わなくてもcollectionを使えばスマートに書けると。
<% @posts.each do |post| %> <%= render partial: "post", locals: { post: post } %> <% end %>
省略可能
逆にややこしい気もするのですが、partialやlocalsを省略して書くこともできます。
以下の3つは全て同じことを言っています。
<%= render partial: "post", locals: { post: @post } %>
<%= render "post", post: @post %>
<%= render @post %>
3つ目とか省略しすぎてて逆にわからないですけどね。ファイル名とインスタンス変数名が同じ場合はここまで省略できるみたいです。
注意としては、partialだけとかlocalsだけの省略はできないみたいなので、両方省略するか両方省略しないかです。
以下のような記述はNGです。
<%= render "post", locals: { post: @post } %>
まとめ
- 部分テンプレートを使うとビューをすっきりさせられる
- "_"から始まるファイルを作成してその中に記述する
- renderで呼び出し、localsやcollectionでインスタンス変数を与えられる