読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

Railsでリダイレクトをするredirect_toメソッドの使い方

Rails初級 Rails Controller

Railsのコントローラーで他のURLにリダイレクトをするには、redirect_toメソッドを使います。
リダイレクト(redirect_toメソッド)とレンダー(renderメソッド)の使い分け、redirect_toメソッドの使い方について説明します。

動作確認

  • Rails 4.1

目次

  1. リダイレクトとは
  2. いつリダイレクト(redirect_to())し、いつレンダー(render())をするか
  3. redirect_toメソッドの使い方

1. リダイレクトとは

HTTPリダイレクトは、「サーバがブラウザからアクセスされたリクエスト(URL)を処理できないけど、できるURLを教えるからそっちへアクセスして」という挙動です。
具体的には、サーバからブラウザにレスポンスとして「リダイレクト先のURL + 永続的(ステータスコード 301)か一時的(ステータスコード 307)かを示すステータス情報」が返され、ブラウザはそのリダイレクト先のURLに自動でアクセスします。そのため、ユーザからはリダイレクトしているかどうかはほぼ画面表示からだけでは分かりません。

2. いつリダイレクト(redirect_to)し、いつレンダー(render)をするか

基本的に、

  • データを追加、更新、削除するときは、「リダイレクト」
  • データの取得して表示するときは、「レンダー」

をします。

具体的なソースコードを見てみましょう。
下記は商品登録画面で「登録」ボタンを押されたときの処理です。

 1: # POST /products
 2: def create
 3:   @product = Product.new(product_params)
 4: 
 5:   if @product.save  # productの保存に成功した場合、商品詳細画面にリダイレクト
 6:       redirect_to @product, notice: '商品を登録しました。'
 7:   else # productの保存に失敗した場合、商品登録画面をレンダリング
 8:       render :new
 9:   end
10: end

上記のソースコードでは、6行目でデータの追加(商品の登録)がされたときにリダイレクトしています。
もし、ここでリダイレクトの代わりにレンダリング(renderメソッド)だったらどうなるでしょうか。

ユーザが遷移先のページでブラウザの更新ボタン(F5)を押した場合、ブラウザが前回と同様のアクセス(POST /products)を繰り返してしまうので、createアクションが実行され、同じ商品がデータベースに登録されてしまいます。
ECサイトの商品購入時にこのようなことが起こったら、余計な代金を払わないといけないことになって大変です。

そのため、リダイレクトをしています。リダイレクトをすることにより、前回のアクセスが商品の詳細画面への遷移(GET /products/:id)になるので、更新ボタンを押しても、商品データが重複してデータベースに登録されてしまうという問題は発生しません。

3. redirect_toメソッドの使い方

URLにリダイレクト

指定したパスにリダイレクトします。
このとき、*_pathではなく*_urlを使います。
さらに、notice, alertというオプションが使え、flash[:notice]、flash[:alert]に値を設定できます。

# flash[:notice]にメッセージを設定し、products_urlにリダイレクトする
redirect_to products_url, notice: 'noticeメッセージ'

# flash[:alert]にメッセージを設定し、products_urlにリダイレクトする
redirect_to products_url, alert: 'alertメッセージ'

# 商品の詳細画面にリダイレクトする
# Railsは@productを、商品の詳細画面へのURLに自動で変換する
redirect_to @product

参照元にリダイレクト

リクエスト内のRefererヘッダ(HTTP_REFERER)で指定されたURLにリダイレクトします。
基本的にはRefererヘッダには前回アクセスしたURLが格納されています。

redirect_to(:back)

永続的なリダイレクト

デフォルトではすべてのリダイレクトが一時的なもの(ステータスコード 307)です。
サイト移動など永続的なリダイレクトを実施したい場合は、ステータスコードを指定する必要があります。

redirect_to("http://new.home", status: 301)


以上です。
よくわからない箇所や間違っている箇所がありましたら、コメント頂けると助かります。