0
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?

【Rails】renderとredirect_toの使い分け

Posted at

はじめに

こんにちは。アメリカにて独学でエンジニアを目指している者です。
Railsでコントローラを実装していると、ビューを表示させたいときにはrender、別のアクションに転送したいときにはredirect_toを使う場面がよくあります。
この2つのメソッドは見た目こそ同じように「画面に何かを返す」ように見えますが役割や仕組みが大きく異なります。
本記事では、Railsにおけるrenderredirect_toの違い、使い分けのポイント、そしてベストプラクティスについて解説します。


renderredirect_toの基本的な違い

1. renderとは?

  • その場でビューを表示する。
  • 同一リクエスト内でテンプレートをレンダリング(描画)するので、リクエストは新規に発行されない
  • URLは変わらない。例えば/usersにPOSTリクエストを送信している最中にrender :newを行うと、ブラウザのアドレスバーは依然として/users(POST送信元)のままです。
典型的な使用例:バリデーションエラー時の再表示
def create
  @user = User.new(user_params)
  if @user.save
    # 省略
  else
    # フォームの入力不備があればnewフォーム画面を再表示
    render :new, status: :unprocessable_entity
  end
end

上記のようにフォーム送信後にエラーがあった場合、すでに入力された値やエラーメッセージを表示するためにrender :newを使います。入力値を再利用できるように、同じリクエスト内でテンプレートを描画しているわけです。

2. redirect_toとは?

  • ブラウザに対して別のURLを再度リクエストするよう命じる。
  • HTTPステータスコードは通常「302 Found」や「303 See Other」(Railsによってリクエストの種類に応じて使い分け) が返され、ブラウザはその指示に従って別のアクションをGETリクエストとして再度呼び出します。
  • URLが変わる。たとえばredirect_to @userと書くと、/users/:id(showアクション)へ転送されます。
典型的な使用例:リソースの作成や更新が成功した後
def create
  @user = User.new(user_params)
  if @user.save
    flash[:success] = 'Welcome to the App!'
    redirect_to @user  # `/users/:id` へリダイレクト
  else
    render :new, status: :unprocessable_entity
  end
end

新規作成が成功した場合などにredirect_toを使うのは、画面を再表示した際に再度POST(またはPATCH/PUT等)が送信される二重投稿を防ぐためです。これはPOST/REDIRECT/GETパターンと呼ばれ、実務でもよく使われます。


使い分けの理由

1. 二重投稿(POSTリクエストの再送信)防止

ユーザーがフォームを送信するときには、サーバーにPOSTリクエストが送られます。もしエラーではなく成功時にそのままrenderを使うと、ユーザーがページを更新(リロード)しただけで再度同じPOSTリクエストが送信されてしまいます。
これにより同じデータが重複して作成されるリスクがあるため、成功時はredirect_toで別のアクションへ飛ばし、ブラウザにGETリクエストを再送信させることがRailsの流儀になっています。

2. ユーザー体験(UX)の向上

redirect_toするとURLが正しくリソースを表すもの(例:/users/1)になるので、ユーザーがブックマークしたり、URLを共有したりするときに便利です。
renderの場合はURLが変わらず、フォーム送信時にエラーが出てもアドレスバーのURLが変わらないため、ユーザーにとってはどの画面を見ているかわかりにくいことがあります。しかし、入力エラーの際はその場でフォームとエラーメッセージを再表示したいので、render :newを用いるのは自然です(また別のURLにリダイレクトしてしまうと、エラー情報を渡す手間が増えてしまいます)。

3. RESTfulな設計

Railsの基本原則はRESTfulな設計です。

  • 新規作成→POSTを受けて→createアクション→成功時にredirect_to show
  • 更新→PATCH/PUTを受けて→updateアクション→成功時にredirect_to show

こうした一連の操作はAPIとしても分かりやすく、コントローラ内のフローも整理しやすくなります。


サンプルコード:renderredirect_toの使い所

ここでは簡単なUserモデルを例に示します。

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      # 成功時:フラッシュメッセージをセットし、showアクションへリダイレクト
      flash[:notice] = "User was successfully created."
      redirect_to @user
    else
      # 失敗時:newアクションのフォーム画面を再表示
      render :new, status: :unprocessable_entity
    end
  end

  def show
    @user = User.find(params[:id])
  end

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end
  • 成功(バリデーション通過)

    • @user.saveがtrueを返す
    • flash[:notice]にメッセージを設定
    • redirect_to @userが呼ばれ、ブラウザは/users/:idへGETリクエストを送る
    • コントローラはshowアクションが呼ばれ、詳細ページを表示
  • 失敗(バリデーションNG)

    • @user.saveがfalseを返す
    • render :newを呼び出し、同じリクエスト内でnewビューを描画
    • @userにはエラー情報が入っているため、ビューでエラーメッセージが表示される
    • URLは/users(POST送信先)のまま変わらないが、この場合はユーザーの入力エラーを即座に表示できるため利便性が高い

よくある質問と注意点

Q1. 成功時にrender :showではダメなの?

  • 成功後にrender :showを使うことは技術的には可能ですが、フォームの二重投稿を防げないなどの問題が起きます。また、ユーザーのブラウザのURLがPOSTのままになり、リロードするとまたPOSTが実行される可能性があります。したがって**redirect_toを使うのがベストプラクティス**です。

Q2. バリデーションエラーのときにredirect_toしたい

  • エラー情報や入力途中のフォーム内容を引き継ぐのが難しくなります。通常はリダイレクト先でエラーメッセージを表示するための仕組みが必要になるでしょう。
    Railsの一般的なパターンは、エラー時はrender :newrender :editで同じリクエスト内でエラー表示をすることです。

Q3. renderredirect_toどちらがパフォーマンスに優れているの?

  • どちらを選ぶかはアプリのフローで決めるべきで、パフォーマンスが決定的な要因になることはほとんどありません。むしろ二重送信ユーザーの操作性を考慮した上で選択するのが重要です。

Q4. redirect_to先を動的に変更したい

  • Railsではredirect_to user_path(@user)のようにヘルパーメソッドを使ってURLを動的に生成できます。redirect_to @userはこのヘルパーを裏で使っているので、オブジェクトを渡すだけで適切なパスを計算してくれます。

まとめ

  • render: 同じリクエスト内でテンプレートを描画。URLはそのまま。バリデーションエラー時のフォーム再表示などに使う。
  • redirect_to: ブラウザが改めて別のURLにアクセス。URLが変化し、二重投稿防止にもなる。成功時の処理や別ページへの誘導に使う。

Railsでは「失敗時はrender、成功時はredirect_to」が基本パターンと言えます。これはユーザー体験向上やデータの重複作成防止につながるためです。

0
0
1

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
0
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?