部分テンプレートをrenderするときのcollectionってなに?

部分テンプレートをレンダリングするときに、ローカル変数を渡す時があるけれど、何種類も渡し方があるので、その中に出てくるcollectionについて考えていきます。

前提として、postコントローラー、postモデルが存在し、

def index
  @posts = Post.all
end
<%= post.title %>
<%= post.body %>

とします。

collectionの使い方

まず、collectionをつかわずに、eachを使って繰り返しレンダリングさせると、

<% @posts.each do |post| %>
  <%= render 'post', post: post %>
<% end %>

と表現できます。しかしこれでは毎回レンダリングをするため、負荷がかかってしまいます。 collectionを使うと、

<%= render partial: 'post', collection: @posts %>

と書くことで、内部で要素1つずつを取り出して処理をしてくれるため、何度もレンダリングをしません。負荷がかからないし、早い。また、部分テンプレートに渡る変数名は、partialで指定した値(post)になるので注意が必要。

collectionの省略記法

<%= render @posts %>

とかなり省略して書くことができるが、これが成立するためにはいくつかの決まりがある。

  1. 部分テンプレートが呼び出し元のテンプレートと同じディレクトリ内にある
  2. 部分テンプレートのファイル名がオプションで指定した変数の単数形である
  3. 部分テンプレート内で使用する変数名が、オプションで指定した変数の単数形である

今回でいうと、1は、呼び出し元のindex.html.erbと部分テンプレートの_post.html.erb同じディレクトリ内にあることが必要。2は、オプションで指定した変数名が@postsなので、部分テンプレートは単数形の_post.html.erbであることが必要。3は、オプションで@postsを渡しているので、部分テンプレート内で使用する変数名は、postであることが必要。 上記3つが守られていればかなり短いコードが書ける。

参考 https://b1840943.hatenablog.jp/entry/2018/05/24/221420 https://himakuro.com/rails-render-collection