#はじめに
いきなりですが、redirect_to
とrender
って、初めて見たときは、両者の違いがよく分からなかったですよね。
深掘りして、一緒に学んでいきましょう!
#redirect_toとrenderの違い
redirect_to: HTTPリクエストをサーバーに送り、ユーザーはそこから返ってくるHTMLが表示される。
render: アクションの中で、呼び出すViewファイルを指定するメソッド。
言葉だけだと、分かりづらい部分があると思うので、それぞれの処理の流れについて解説します。
#それぞれの処理の流れについて
①controllerの処理でredirect_toを実行
②redirect_toの引数で指定したURLにHTTPリクエスト(GET!!)を実行
③HTTPリクエスト(GET!!)されたURLに対応するルーティング処理を実行
④ルーティング処理に対応したcontroller、アクションが呼び出され処理を実行
⑤処理に応じたviewのレンダリングを実行
①controller(redirect_to) → ②HTTPリクエスト(GET!!) → ③ルーティング → ④controller → ⑤view
①controllerの処理でrenderを実行
②renderのオプションで指定したviewファイルを表示する
①controller(render) → ②view
ここで注意が必要なのは、redirect_toの指定先は、必ずGETメソッドのルーティングになるということです。
#redirect_toやrenderの指定がない場合
たまに見かけますよね。
下の状態のようなコントローラーを。
class BooksController < ApplicationController
def index
end
end
アクション内に、何も記載がない場合は、自動的にrenderが実行されます!!
つまり、上の場合だと、render 'index'
が省略されているものと考えられ、このアクションからviews/books/index.html.erb
が呼び出されます。
#よく見る記載方法
それではここで、よく使われているredirect_toとrenderの記述例について見てみましょう!
class BooksController < ApplicationController
def create
@book = Book.new(book_params)
@book.user_id = current_user.id
if @book.save
redirect_to books_path, flash[:notice] = "投稿成功!!"
else
flash.now[:alert] = "投稿失敗!!"
render 'new'
end
end
end
投稿を行う際に、saveメソッドの結果がtrueならば投稿一覧ページにリダイレクトし、falseなら新規投稿用のページを再表示するように設定しています。
※render 'アクション名'
で同じコントローラの別アクションのViewを表示できます。
コントローラ名を指定することで、他のコントローラのViewも表示できます。
#なぜfalseの場合はrenderを使用するのか
renderを利用して、viewファイルを表示する際に、アクションを呼び出していないことにお気づきでしょうか。
↑のrender 'new'
は、books/new.html.erb
を表示させているだけであり、newアクションを経由しているわけではないのです。
今回のパターンだと、投稿に失敗しているからnewページを表示させたいのですが、redirect_toを使用してしまうと、newアクションを呼び込み、インスタンス変数に空のメソッドを渡してしまうことで、newアクションがリセットされた状態になるので、ユーザーが打ち込んだデータが消えます。
よって、エラーメッセージを打ち出す為の情報も消えてしまう為、ユーザーは「なぜ投稿できなかったのか」を窺い知ることができなくなります。
ややこしいですが、大事な分岐点を決めるものなので、腹落ちするまで向き合ってもらえればと思います。
##(補足)render時のフラッシュメッセージについて
本筋とは離れてしまうので、詳細は述べませんが、表示したビュー内にメッセージを出したい場合、以下のように記述します。
flash[:notice] = "メッセージ"
または
notice: "メッセージ"
flash.now[:alert] = "メッセージ" #nowがついている!!!!
#おわりに
初心者の方が間違いやすいredirect_toとrenderの違いについて説明しました!!
解説している中で、自分自身勉強になることが多く、アウトプットの重要性を痛感しています。