基本

Ruby on Railsのリダイレクト(redirect_to)の使い方

Ruby on Railsのredirect_toは、ブラウザに別のURLへのリダイレクトを指示するメソッドです。フォーム送信後の画面遷移や、認証が必要なページへの未ログインユーザーの誘導など、様々な場面で使用されます。この記事では、redirect_toの基本的な使い方からフラッシュメッセージの組み合わせまで解説します。

基本的な使い方

redirect_toに遷移先のURLまたはパスヘルパーを指定すると、ブラウザに302リダイレクトが返されます。

app/controllers/test_controller.rb
class TestController < ApplicationController
  def index
    redirect_to "/test2"
    # http://127.0.0.1:3000/test2にリダイレクトされる
  end
end

上記のコードでは、/にアクセスすると自動的に/test2に転送されます。ブラウザのURLバーも遷移先のURLに変わります。

パスヘルパーを使ったリダイレクト

URLを文字列で直接指定するよりも、Railsのパスヘルパーを使うのが推奨されます。ルーティングの変更に強く、タイプミスも防げます。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to post_path(@post)  # /posts/:idにリダイレクト
    else
      render :new
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    redirect_to posts_path  # /postsにリダイレクト
  end
end

post_path(@post)/posts/1のようなURLを生成し、posts_path/postsを生成します。モデルオブジェクトを直接渡すこともできます。

Ruby
# 以下は同じ意味
redirect_to post_path(@post)
redirect_to @post

フラッシュメッセージ付きリダイレクト

リダイレクト先のページにメッセージを表示したい場合は、noticealertオプションを使います。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post, notice: "投稿を作成しました"
    else
      render :new
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    redirect_to posts_path, alert: "投稿を削除しました"
  end
end

フラッシュメッセージはリダイレクト先で1回だけ表示され、次のリクエストでは自動的に消えます。レイアウトファイルに以下のようにフラッシュ表示を追加しておきます。

app/views/layouts/application.html.erb
<% if flash[:notice] %>
  <div class="alert alert-success"><%= flash[:notice] %></div>
<% end %>
<% if flash[:alert] %>
  <div class="alert alert-danger"><%= flash[:alert] %></div>
<% end %>

<%= yield %>

redirect_toとrenderの違い

redirect_torenderは混同しやすいですが、動作が根本的に異なります。

機能 redirect_to render
動作 ブラウザに新しいリクエストを送らせる 現在のリクエスト内でビューを表示
URL 変わる 変わらない
インスタンス変数 リセットされる 保持される
主な用途 保存成功後の画面遷移 バリデーションエラー時のフォーム再表示
ポイント

フォームのバリデーションエラー時にredirect_toを使うと、エラー情報(@post.errors)が失われます。エラーフォームを再表示する場合は必ずrenderを使いましょう。

条件付きリダイレクト

before_actionと組み合わせて、認証チェックやアクセス権限の確認にリダイレクトを使うのが一般的です。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  private

  def require_login
    unless current_user
      redirect_to login_path, alert: "ログインが必要です"
    end
  end
end
注意

redirect_toの後にもコードは実行されます。処理を確実に止めたい場合はredirect_to ... and returnと記述してください。

まとめ

  • redirect_toはブラウザに新しいリクエストを送らせてページ遷移する
  • パスヘルパー(posts_path等)を使うのが推奨される
  • notice:alert:でフラッシュメッセージを付与できる
  • redirect_toはURL変更あり、renderはURL変更なし
  • バリデーションエラー時はrender、保存成功時はredirect_toを使う
  • redirect_to後に処理を止めるにはand returnを付ける