1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rails】redirect_to と render の違いについて調べてみた。

Last updated at Posted at 2020-12-28

Rails コントローラーの create アクションと update アクションで並んでいる redirect と render ですが、どう違うのかいまいち分からなかったので調べました。学び始めたばかりの頃はあまり気にしていませんでしたが、先日2つの違いを質問されてうまく答えられなかったので。。。

####結論

【render】
controller から指定された view を直接呼び出す。
動き: controller → view
データなどの状態はそのままで画面だけ貼り替える

【redirect_to】
http リクエストを受けた場合と同じ処理
動き: controller → URL → route → controller → view
指定したURLに一からアクセスしてデータをすべて取得し直す

####実際にやってみた
①通常の controller ファイルの create アクションで動きを見てみる

tasks_controller.rb
 def create
   @task = Task.new(task_params)
   if @task.save
     redirect_to tasks_path, notice: "タスクを作成しました"
   else
     render :new
   end
 end 

スクリーンショット 2020-12-28 21.20.47.png
バリデーションに引っかかって保存されないようにタスク名は空欄。これで"Create Task" を押すと、、、
スクリーンショット 2020-12-28 21.20.47.png
保存されず、"render :new"が実行されました。入力したデータはそのままです。

② render を redirect に置き換えてみた。Prefixで render の場合と同じく new.html.erb を呼び出すように指定します。

tasks_controller.rb
def create
  @task = Task.new(task_params)
  if @task.save
    redirect_to tasks_path, notice: "タスクを作成しました"
  else
    redirect_to new_task_path #render を redirect_to に置き換えた
  end
end

スクリーンショット 2020-12-28 21.20.47.png
今回も、わざとタスク名を空欄で保存。"Create Task" を押すと、、、
スクリーンショット 2020-12-28 20.21.00.png
入力していた分が全て空欄になってしまいました。今回はテストで文字数が少ないから問題ありませんが、文字数の多いブログを投稿しようとしてエラーが起きた場合、書いた文章が水の泡ということになってしまいます。

何が起きているのか、困った時の Rails ガイドです。

####Railsガイドの説明

render と redirect_to について、 Railsガイドの説明は下記。

Railsガイド レイアウトとレンダリング 2.3 redirect_toを使用する

renderはレスポンス構成時にどのビュー (または他のアセット) を使用するかを指定するためのものです。redirect_toメソッドは、この点においてrenderメソッドと根本的に異なります。redirect_toメソッドは、別のURLに対して改めてリクエストを再送信するよう、ブラウザに指令を出すためのものです。

Railsガイド レイアウトとレンダリング 2.3.2 renderとredirect_toの違い

redirect_toを実行した後、コードはそこで実行を終了し、ブラウザからの次のリクエストを待ちます (通常のスタンバイ状態)。その直後、redirect_toでブラウザに送信したHTTPステータスコード302に従って、ブラウザから別のURLへのリクエストがサーバーに送信され、サーバーはそのリクエストを改めて処理します。それ以外のことは行っていません。

ちょっと分かりにくいですが。。。

もう一つこちらの記事も大変参考にさせていただき、何が起きているか分かってきました。
render と redirect の違い

render は入力した内容を保持しつつ、指定された view を直に呼び出して画面を張り替える。redirect_to は http リクエストを改めて要求して、route や controller を通って指定された view を一から呼び出し直しているということのようです。

ちなみに、もう一つ試してみました。

③ redirect_to を render に変えてみる
タスクの保存が成功したら index アクションに移動する設定にしてみました。

tasks_controller.rb
def create
  @task = Task.new(task_params)
  if @task.save
    render :index
  else
    render :new
  end
end

今度はタスクが保存されるように、タスク名も含めて全ての項目を入力。
スクリーンショット 2020-12-28 20.51.52.png

これで Create Taskを押してみると。。。
スクリーンショット 2020-12-28 15.45.40.png
エラーが発生しました。これは index.html.erb の インスタンス変数 @task に何も入っていないためと思われます。@task は controller の index アクションで生成されます。つまり指定された view を呼び出そうとしているものの、controller の index アクションを経由していないのでインスタンス変数が作成されていない。そのためエラーが発生していると思われます。

一方でredirect_toを使ってみると。

tasks_controller.rb
def create
  @task = Task.new(task_params)
  if @task.save
    redirect_to tasks_path
  else
    render :new
  end
end

保存されるように、全ての項目を入力。
スクリーンショット 2020-12-28 20.51.52.png
Create Task を押すと。。
スクリーンショット 2020-12-28 23.14.38.png
タスクが保存され、 index の view に移動してくれました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?