はじめに
本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。
今回の疑問点
今回の疑問点は、
redirect_to
とrender
の処理の違い
です。
以前、バリデーションの設定を行った際に上記について疑問を抱きました。
また、処理の違いをしっかりと理解しておかないとエラーの発生につながるので今回まとめていきます。
疑問点についての解説
###結論
結論から記載しますとredirect_to
とrender
の処理はそれぞれ以下のようになります。
####redirect_toの処理の流れ
①controller(redirect_to) → ②HTTPリクエスト → ③ルーティング → ④controller → ⑤view
①controllerの処理でredirect_to
を実行
②redirect_to
の引数で指定したURLにHTTPリクエストを実行
③HTTPリクエストされたURLに対応するルーティング処理を実行
④ルーティング処理に対応したcontroller、アクションが呼び出され処理を実行
⑤処理に応じたviewのレンダリングを実行
####renderの処理の流れ
①controller → ②view
①controllerの処理でrender
を実行
②renderのオプションで指定したviewファイルを表示する
###特に注意を要するポイント
redirect_toとrenderの処理の違いの中でも、render
を使用してviewファイルを表示したときにはアクションを呼び出し処理をしているわけではないことに注意しましょう。
以下で具体例を用いて説明します。
class BooksController < ApplicationController
def index
@books = Book.all
@book = Book.new
end
def create
@book = Book.new(book_params)
@book.user_id = current_user.id
if @book.save
redirect_to book_path(@book), notice: "You have created book successfully."
else
render 'index'
end
end
end
上記の記述で、render
の処理の際にindexアクションは呼び出されず、createアクションから直接index.html.erbを表示しするためエラーが発生します。
indexアクションをご確認ください。
@books = Book.all
@book = Book.new
2つのインスタンス変数が定義されております。
次にcreateアクションをご確認ください。
@book = Book.new(book_params)
@book.user_id = current_user.id
のみでindexアクションで定義されていた
@books = Book.all
が定義されていません。
先ほども申し上げた通り、render
処理の際にはindexアクションは実行されないので、上記の記述のまま、処理をしてもcreateアクション内では@books = Book.all
が定義されていないため、Viewがデータを取得できずにエラーとなります。
以下のように記載することでエラーを解消することができます。
class BooksController < ApplicationController
def index
@books = Book.all
@book = Book.new
end
def create
@book = Book.new(book_params)
@book.user_id = current_user.id
if @book.save
redirect_to book_path(@book), notice: "You have created book successfully."
else
@books = Book.all #追記
render 'index'
end
end
end
また、render
処理の際にはindexアクションが実行されないことから、@book = Book.new
も実行されず、フォームの中に入力した内容がそのまま表示されます。
まとめ
最後にポイントをまとめます。
- render処理の場合にはアクションが実行されない。
- 上記のことから、render処理を行う際には、呼び出すViewファイルに渡す変数が全てrender処理を行うアクションに定義されているか注意する必要がある。