render

Railsを学習していてrenderを使うことは多々あります。

なんとなく使っていて理解が浅いと感じたので、一度しっかりおさらいして

renderを使いこなせるようにしたい、と思いアウトプットすることに。


renderを使う場面

renderを使う場面は大きく分けて2種類あります。


  • controllerで使用
  • viewで使用


controllerで使用

controllerでは、renderを使うことで指定したviewファイルを呼び出します。

# users_controller

def create
  @user = User.new(user_params)
  if @user.save
    redirect_to login_path
  else
    render :new
  end
end

private

def user_params
  params.require(:user).permit(:name, :email)
end

このコードでは新規ユーザーの作成が成功したときはログインページへ遷移、

失敗したときはusers/new.html.erbを呼び出す、という流れです。

redirect_toは引数で指定したpathをサーバーにリクエストし、レスポンスを表示します。

renderはアクションは経由せず直接users/new.html.erbを表示します。


viewで使用

viewではrenderを使うことで部分テンプレートを呼び出します。

posts/new.html.erbとposts/edit.html.erbのように、新規投稿ページと投稿編集ページがあるとします。

投稿のタイトルと本文を入力するフォームは同じものを使い回せばコード量を削減できますよね。

そんなときに部分テンプレートとしてフォーム部分を別ファイルに書き出してしまって汎用化させます。

部分テンプレート用のファイルは頭にアンダーバー(_)を付けます

# posts/_form.html.erb

<%= form_with model: post, local: true do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title, class: 'form-control' %>

  <%= f.label :body %>
  <%= f.text_area :body, class: 'form-control' %>

  <%= f.submit class: 'btn btn-primary' %>
<% end %>

新規投稿ページで呼び出してみます

呼び出す際はアンダーバーは付けません。

# posts/new.html.erb

<%= '新規投稿' %>
<%= render partial: 'form' %>
# 下の形に省略可
<%= render 'form' %>
# 同じディレクトリにある場合はディレクトリ名を省略できます

部分テンプレート内で変数を使用する場合はlocalsオプションで変数を定義します。

<%= render partial: 'form', locals: { post: @post } %>
# { 部分テンプレート内で使う変数 : 変数に入れる値 }
# 下の形に省略可
<%= render 'form',  post: @post %>

わざわざインスタンス変数をローカル変数に定義し直すのは、パーシャルの中でインスタンス変数を参照してしまうと、パーシャルとコントローラが密結合してしまってパーシャルの再利用性が低くなるからです。

次はcollectionオプションを見てみます。

posts/index.html.erbで全てのpostを表示する次のようなコードがあったとします

<% @post.each do |post| %>
  <%= post.title %>
  <%= post.body %>
<% end %>

タイトルと本文の部分は部分テンプレート化できそうです。

# _post.html.erb

  <%= post.title %>
  <%= post.body %>

これをeachで回すと

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

となります。

これをさらに

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

さらに

<%= render @posts %>

と、ここまで省略できます。


最後に

今までふわっとした理解で使っていましたが、アウトプットを通して少し理解が深まった気がします。

他にもオプションがあるようですが僕が今まで使ってきたもののおさらいなので以上としておきます。

もし間違っている箇所がありましたらコメントいただけますと幸いです。

最後まで読んでくださりありがとうございました。