📚

【Rails】サンプルで見るrenderとridirect_toの違い

2023/06/17に公開

サンプルアプリの作成

まずはRailsのscaffoldを使い、サンプルアプリを作成します。

rails new sample_app
cd sample_app
rails g scaffold User name:string detail:text
rails db:migrate

ユーザー一覧ページ

ユーザー追加ページ

バリデーションを設定します。
Nameが空欄の場合と、Detailの文字数が50を超える場合にエラーが出るようにします。

user.rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :detail, length: { maximum: 50 }
end

これで準備が整いました。
それでは、わかりやすいようにバリデーションエラーを起こして、
renderとredirect_toの動きを見ていきましょう。

users_controller_rb
def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to user_url(@user), notice: "User was successfully created." }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        # format.html { redirect_to new_user_path }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

New userのページで「Create user」をクリックした際に、バリデーションに引っ掛かると上記コードのelseの処理が実行されます。

Name 
山田太郎
Detail
サンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプルサンプル

とします。
まずは、renderだとどうなるか見ていきましょう。

エラー文が出力されています。
NameとDetailはそのまま残っています。

次に、ridirect_toだとどうなるか見ていきましょう。

users_controller_rb
def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to user_url(@user), notice: "User was successfully created." }
        format.json { render :show, status: :created, location: @user }
      else
        # format.html { render :new, status: :unprocessable_entity }
        format.html { redirect_to new_user_path }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

Create userをクリックしたら、入力してたものがなくなってしまいました。

まとめ

renderは、現在のコントローラ(または他の指定されたコントローラ)から指定されたビューに直接遷移します。新しいリクエストは生成されません。

redirect_toは、指定されたURLに新しいHTTPリクエストを発行し、そのURLが関連付けられたルーティング設定に基づいて新しいコントローラアクションを実行します。そして、そのコントローラアクションは新しいビューを表示します。

  • render     : controller → view
  • redirect_to   : controller → URL → route → controller → view

Discussion