更新日:
【Rails】 renderメソッドの使い方を徹底解説!
renderメソッドとは、呼び出すテンプレート(ビュー)ファイルを指定するメソッドです。コントローラー・ビューどちらでも使うことができます。
1
render ファイル名、アクション名など
railsでは、コントローラーのアクションが動くと、その後同名のビューファイルが呼び出され表示されます。
その際、コントローラーやビューで特定のビューファイルをレンダリングしたい時に使用します。
renderメソッドの使い方
この章では、renderメソッドの使い方について解説します。
レンダリング(rendering)とは
レンダリングとはビューファイルから最終的にhtmlにコンパイルされたモノをブラウザで読み込んで表示させることを言います。
ビューファイルはただの文字の羅列なので、そのまま表示しても文字しか表示されません。
ですが、google chrome
やsafari
などのブラウザがそのコード通りに見た目を作成し、ユーザーに見た目を返してくれます。
その流れをレンダリングと呼びます。
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
これは下記のように省略して書くこともできます。
1
render :new
partial
上にも出てきましたが、明示的に部分テンプレートを呼び出すときに使用します。
1
<%= render partial: "部分テンプレートファイル名" %>
template
他のコントローラーのテンプレートを呼び出すときに使用します。
1
render template: "コントローラー名/アクション名"
(例)messagesコントローラー
のcreateアクション
が動いた後にusersコントローラー
のshowアクション
を表示させる
1
2
3
4
def create
Message.create(messeage_params)
render template: "users/show"
end
layout
layoutを呼び出します。
layoutとは一つのビューファイルではなくてapplication.html.erb
のような複数のビューで使われるレイアウトです。
コントローラー単位でレイアウトを切り替える場合はコントローラーに下記のように記述します。
1
layout "レイアウト名"
コントローラーの各アクションでレイアウトを指定する場合は下記のように記述します。
1
2
3
def index
render layout: "レイアウト名"
end
layoutについての詳細はlayoutメソッドの使い方をマスターしよう!を参照してください。
file
アプリケーション外のテンプレートを表示させるときに使用します。
1
render file: "別のアプリケーションの呼び出したいテンプレートファイルのパス"
text
文字列を直接表示させたいときに使用します。
1
<%= render text: "ピカイチわかりやすい" %>
plain
textと同じく文字列を表示するときに使用します。
※rails5.1未満の場合はtextを使用します。
xml
オブジェクトをxml形式に変更して表示させたいときに使用します。
1
2
3
4
def index
text = { name: "ピカわか", url: "pikawaka" }
render xml: text
end
json
オブジェクトをjson形式に変更して表示させたいときに使用します。
1
2
3
4
def index
text = { name: "ピカわか", url: "pikawaka" }
render json: text
end
RailsでJSON形式のデータを扱い方の詳細は、「JSON形式のデータを返却する方法とは?」を参考にしてください。
inline
Rubyのコードを展開して表示させたいときに使用します。
1
2
3
4
def index
@name = "ピカわか"
render inline: "<%= @name %>"
end
ここをtextで指定するとこうなってしまいます。
またビューファイルに渡す変数なので必ずインスタンス変数にしておかないとエラーになるので気をつけましょう。
status
ビューが呼び出されたときに返されるステータスコードを変更するときに使用します。
何も指定しないとちゃんとビューが返っているのでステータスコードは200です。
1
render plain: "エラーです!"
1
render plain: "エラーです!", status: 404
このように記述すると「エラーです!」という文字が表示され、ちゃんとビューが返っているのに404のステータスコードを返すことができます。
Railsを体系的に学べる1冊
こちらの「現場で使える Ruby on Rails 5速習実践ガイド」は、Ruby on Railsを扱うための最低限必要なRubyの基礎からRailsアプリケーションの開発方法、現場で必要な知識まで体系的に学ぶことができます。
初学者にはやや難しい内容も含まれていますが、わかりやすい図と噛み砕いた文章で解説しています。何よりも実際に手を動かしてアプリケーションを開発しながら学べるので、より知識を吸収することができます。
今まで学習したことの復習としても、開発現場でのリファレンスブックとしても役立つ1冊です!
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の場合
- newアクションが実行される
- 1回ビューファイルがリセットされる
- newのビューファイルがレンダリングされる
- newの見た目が表示される
このようにnewアクションを指定してしまうとnewアクションが実行された後にnewのビューファイルがレンダリングされます。
renderの場合
- アクションを通さずにnewのビューファイルがレンダリングされる
- 入力された情報はそのまま
- 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メソッドは呼び出すテンプレートファイルを指定できるメソッド
- オプションを使うと様々な方法で呼び出すことができる