すでにメンバーの場合は

無料会員登録

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

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

Pikawakaにログイン

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

Rails

【Rails】 renderメソッドの使い方を徹底解説!

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

renderメソッドとは、呼び出すテンプレート(ビュー)ファイルを指定するメソッドです。コントローラー・ビューどちらでも使うことができます。

コントローラ | renderメソッドの基本構文
1
render ファイル名、アクション名など

railsでは、コントローラーのアクションが動くと、その後同名のビューファイルが呼び出され表示されます。

その際、コントローラーやビューで特定のビューファイルをレンダリングしたい時に使用します。

renderメソッドの使い方

この章では、renderメソッドの使い方について解説します。

レンダリング(rendering)とは

rendering

レンダリングとはビューファイルから最終的にhtmlにコンパイルされたモノをブラウザで読み込んで表示させることを言います。
ビューファイルはただの文字の羅列なので、そのまま表示しても文字しか表示されません。
ですが、google chromesafariなどのブラウザがそのコード通りに見た目を作成し、ユーザーに見た目を返してくれます。
その流れをレンダリングと呼びます。

renderメソッドはそのレンダリングする元となるファイルを指定することができるメソッドです。
renderメソッドが実行されると現在のhtmlのコードが、renderメソッドで指定したビューファイルのhtmlに上書きされて表示されるイメージです。

ビューファイルでの書き方

ビューファイルでは下記のように定義します。

ビューファイル
1
<%= render 'ファイル名' %>

ビューファイルでrenderメソッドを使うときは部分テンプレートを呼び出す場合がほとんどです。

部分テンプレート

部分テンプレートとは複数のビューファイルの共通部分として作成するビューファイルです。

renderメソッドを使って部分テンプレートを呼び出す際は、部分テンプレートを呼び出していることを明示的にするためにpartialオプションを使います。

ビューファイル
1
<%= render partial: 'ファイル名' %>

部分テンプレートを呼び出す際のより詳しい書き方は、「部分テンプレートの使い方」の記事を参照してください。

コントローラー内での書き方

railsではコントローラーの各アクションが動くとアクションと同名のビューファイルがレンダリングされます。

(例)messagesコントローラーindexアクションが動く
    ↓
   viewsフォルダ内のmessegesフォルダ内のindex.html.erbがレンダリングされる

このとき、アクションに対応するビューをレンダリングしたくないときにrenderメソッドを使用します。

renderメソッドのオプション

renderメソッドはオプションを使うことによって様々な方法でレンダリングすることができます。

それぞれのオプションの説明と実際の使い方を確認してみましょう。

action

動いたアクションとは別のアクションのテンプレートを表示させます。

コントローラー
1
2
3
4
5
# 例 createアクションが動いた後にnewアクションを表示させる
def create
  Message.create(message_params)
  render action: :new
end

action

これは下記のように省略して書くこともできます。

コントローラー
1
render :new

partial

上にも出てきましたが、明示的に部分テンプレートを呼び出すときに使用します。

ビューファイル
1
<%= render partial: "部分テンプレートファイル名" %>

partial

template

他のコントローラーのテンプレートを呼び出すときに使用します。

コントローラー
1
render template: "コントローラー名/アクション名"

(例)messagesコントローラーcreateアクションが動いた後にusersコントローラーshowアクションを表示させる

コントローラー
1
2
3
4
def create
  Message.create(messeage_params)
  render template: "users/show"
end

controller

layout

layoutを呼び出します。
layoutとは一つのビューファイルではなくてapplication.html.erbのような複数のビューで使われるレイアウトです。
コントローラー単位でレイアウトを切り替える場合はコントローラーに下記のように記述します。

コントローラー
1
layout "レイアウト名"

コントローラーの各アクションでレイアウトを指定する場合は下記のように記述します。

コントローラー
1
2
3
def index
  render layout: "レイアウト名"
end

layout

layoutについての詳細はlayoutメソッドの使い方をマスターしよう!を参照してください。

file

アプリケーション外のテンプレートを表示させるときに使用します。

コントローラー
1
render file: "別のアプリケーションの呼び出したいテンプレートファイルのパス"

file

text

文字列を直接表示させたいときに使用します。

ビューファイル
1
<%= render text: "ピカイチわかりやすい" %>

text

plain

textと同じく文字列を表示するときに使用します。
※rails5.1未満の場合はtextを使用します。

xml

オブジェクトをxml形式に変更して表示させたいときに使用します。

コントローラー
1
2
3
4
def index
  text = { name: "ピカわか", url: "pikawaka" }
  render xml: text
end

xml

json

オブジェクトをjson形式に変更して表示させたいときに使用します。

コントローラー
1
2
3
4
def index
  text = { name: "ピカわか", url: "pikawaka" }
  render json: text
end

json

RailsでJSON形式のデータを扱い方の詳細は、「JSON形式のデータを返却する方法とは?」を参考にしてください。

inline

Rubyのコードを展開して表示させたいときに使用します。

コントローラー
1
2
3
4
def index
  @name = "ピカわか"
  render inline: "<%= @name %>"
end

inline

ここをtextで指定するとこうなってしまいます。

text

またビューファイルに渡す変数なので必ずインスタンス変数にしておかないとエラーになるので気をつけましょう。

status

ビューが呼び出されたときに返されるステータスコードを変更するときに使用します。
何も指定しないとちゃんとビューが返っているのでステータスコードは200です。

コントローラー
1
render plain: "エラーです!"

200

コントローラー
1
render plain: "エラーです!", status: 404

このように記述すると「エラーです!」という文字が表示され、ちゃんとビューが返っているのに404のステータスコードを返すことができます。

404

Railsを体系的に学べる1冊

こちらの「現場で使える Ruby on Rails 5速習実践ガイド」は、Ruby on Railsを扱うための最低限必要なRubyの基礎からRailsアプリケーションの開発方法、現場で必要な知識まで体系的に学ぶことができます。

初学者にはやや難しい内容も含まれていますが、わかりやすい図と噛み砕いた文章で解説しています。何よりも実際に手を動かしてアプリケーションを開発しながら学べるので、より知識を吸収することができます。

今まで学習したことの復習としても、開発現場でのリファレンスブックとしても役立つ1冊です!

現場で使える Ruby on Rails 5速習実践ガイド
現場で使える Ruby on Rails 5速習実践ガイド

Ruby on Railsの基礎から実践的なノウハウまで学べる!

renderメソッドを使って処理を分岐させよう

コントローラーのcreateアクションやupdateアクション内で保存が失敗した時、renderメソッドを使って処理を分岐させる方法があります。

コントローラー
1
2
3
def create
  Message.create(message_params)
end

上のようにcreateアクション内でcreateメソッドを使って保存する場合、保存ができてもできなくてもcreateのビューがレンダリングされます。
この時の返り値は下記のようにインスタンスの情報になっています。

下の例は保存が失敗した時のものですが、保存ができてもできなくても返り値は同じです。

コンソール
1
2
3
4
[1] pry(main)> Message.create(text: "")
   (0.1ms)  BEGIN
   (0.2ms)  ROLLBACK
=> #<Message:0x007fc568890a50

しかしsaveメソッドを使って保存をすると保存されなかった場合、返り値としてfalseが返ります。

コンソール
1
2
3
4
5
6
7
8
9
10
[1] pry(main)> message = Message.new(text: "")
=> #<Message:0x007fc569b2e630
 id: nil,
 text: "",
 created_at: nil,
 updated_at: nil,
[2] pry(main)> message.save
   (0.8ms)  BEGIN
   (0.2ms)  ROLLBACK
=> false

これを利用して保存が成功した時と成功しなかった時で処理を変えることができます。

コントローラー
1
2
3
4
5
6
7
  def create
    @message = Message.new(message_params)
    if @message.save
      redirect_to root_path and return
    end
    render :new
  end

上のように記述すると保存が成功したときにはルートにリダイレクトさせ、失敗したときにはnewアクションで返るビュー、つまり投稿フォームを表示させることができます。

このときnewアクションを介さないでエラーがなくビューが表示できるのは同じビューファイルを再度呼び出しているからです。

つまりnewアクションが動いた後の状態が残っているから、再びnewアクションを動かす必要がないということですね。

※上のコード内のand returnについては後述します。

エラーメッセージを表示させよう

このときただ入力画面に戻っただけだとユーザーは保存されていないのに気づきません。

そんな時にはnewのビューファイルに下記のようなコードを追加するとvalidationが原因で保存できなかった時にvalidationのエラーメッセージを投稿画面に表示させることができます。

ビューファイル
1
2
3
<% if @message.errors.any? %>
   <p class="red">メッセージを入力してください。</p>
<% end %>

このように"モデルクラスのインスタンス".errors.any?とするとエラーが起こっているかを判定することができます。

最初に投稿画面が表示された時、@message.errorsの中身を確かめてみましょう。

コントローラー
1
2
3
4
  def new
    @message = Message.new
    binding.pry
  end

このようにしてnewアクションが呼び出された時の処理をbinding.pryで止めて@message.errorsの中身を確認してみます。

コンソール
1
2
3
4
5
6
7
8
9
10
[1] pry(#<MessagesController>)> @message.errors
=> #<ActiveModel::Errors:0x007fbbd39c2200
 @base=
  #<Message:0x007fbbd0f1b100
   id: nil,
   text: nil,
   created_at: nil,
   updated_at: nil,
   user_id: nil>,
 @messages={}>

一番最後の行に@messages={}とあります。
これはエラーメッセージがないという意味です。
ですのでビューに記述した部分の<% if @message.errors.any? %>falseが返ります。

コンソール
1
2
[2] pry(#<TweetsController>)> @message.errors.any?
=> false

そのため「メッセージを入力してください。」は表示されません。

投稿画面

それに対し、保存されなかった時を確認してみましょう。binding.pryの位置を下記の場所に変更します。

コントローラー
1
2
3
4
5
6
7
8
  def create
    @message = Message.new(message_params)
    if @message.save
      redirect_to root_path and return
    end
    binding.pry
    render :new
  end

フォームに何も入力しないで送信を押し、createアクションを実行させます。
するとバリデーションに引っかかり保存されないので条件分岐によりnewのビューファイルがレンダリングされます。

その時の@message.errorsの中身を確認してみます。

コンソール
1
2
3
4
5
6
7
8
9
10
[1] pry(#<MesssagesController>)> @message.errors
=> #<ActiveModel::Errors:0x007fbbd42ada68
 @base=
  #<Message:0x007fbbd16c0478
   id: nil,
   text: "",
   created_at: nil,
   updated_at: nil,
   user_id: 1>,
 @messages={:text=>["can't be blank"]}>

このように@messagesの中に文字が入りました。

コンソール
1
2
[2] pry(#<TweetsController>)> @message.errors.any?
=> true

<% if @message.errors.any? %>はこのようにtrueが返ったため「メッセージを入力してください。」が表示されるわけです。

ビューファイル
1
2
3
<% if @message.errors.any? %> # trueになるので下のコードが表示される
   <p class="red">メッセージを入力してください。</p>
<% end %>

メッセージが表示

renderメソッドとredierct_toとの違い

成功したときに使っているredirect_toは、実行するアクションを指定できるメソッドです。

先程の例をみると、成功したときにはredirect_toでルートのビューを表示させ、失敗したときにはrenderでnewアクションで返るビューを指定しています。

どちらも使用することにより表示するビューを指定することができるメソッドです。
では、なぜ失敗したときはrenderメソッドを使用しているのでしょうか?

前述した通り、redirect_toはHTTPリクエストを送り一度アクションを動かした後に同名のビューファイルをレンダリングします。

しかし、renderはHTTPリクエストを送らず、アクションを実行しないで指定したファイルをレンダリングするメソッドです。

今回失敗した場合もredirect_toを使ってしまうとどうなるでしょうか?

redirect_toの場合

  1. newアクションが実行される
  2. 1回ビューファイルがリセットされる
  3. newのビューファイルがレンダリングされる
  4. newの見た目が表示される

このようにnewアクションを指定してしまうとnewアクションが実行された後にnewのビューファイルがレンダリングされます。

renderの場合

  1. アクションを通さずにnewのビューファイルがレンダリングされる
  2. 入力された情報はそのまま
  3. newの見た目が表示される

renderでレンダリングした場合は、投稿フォームに入力していた情報はそのまま残っているので、レンダリング後のビューも同じ状態で表示されます。

2つを比較するとわかるように、1回アクションを実行してしまうと入力済みの情報が一度リセットされてしまうので、また入力しなくてはならなくなります。

入力した情報が多いときにはそのまま残っておいたほうがいいですよね?
そのため失敗した際には、renderメソッドを使って表示するビューを指定するようにしましょう。

renderメソッドを使うときの注意点

renderメソッドは同じアクションの中で2回以上呼び出されるとエラーになります。
下記のコードを見てみましょう。

コントローラー
1
2
3
4
5
6
7
def create
  message = Message.new(message_params)
  if message.save
    render :index
  end
  render :new
end

保存が成功したときはindexのビューをレンダリングするよう記述しました。

一見問題ないように見えますが、保存に成功した際はindexのビューがレンダリングされた後、newのビューもレンダリングしに行きます。

このときDoubleRenderErrorというエラーが発生してしまいます。

このエラーを発生させないようにするには、下記のように「and return」を使います。

コントローラー
1
2
3
4
5
6
7
def create
  message = Message.new(message_params)
  if message.save
    render :index and return
  end
  render :new
end

改行をすればandは不要です。

コントローラー
1
2
3
4
5
6
7
8
def create
  message = Message.new(message_params)
  if message.save
    render :index
    return
  end
  render :new
end

同じアクション内でrenderを2回記述する場合はand returnを使用するということを覚えておきましょう。

この記事のまとめ

  • renderメソッドは呼び出すテンプレートファイルを指定できるメソッド
  • オプションを使うと様々な方法で呼び出すことができる