基本
ドキュメントにある使用方法(よくあるusers_controllerがあるとして)
# URLへリダイレクト(アクションはconfig/routes.rbを参照)
redirect_to URL
# indexアクションへリダイレクト
redirect_to action: 'index'
# usersコントローラのindexアクションへリダイレクト
redirect_to controller: 'users', action: 'index'
# usersコントローラーのshowアクションのid=8へリダイレクト
redirect_to controller: 'users', action: 'show', id: 8
# 前ページへリダイレクト
redirect_to :back
# indexアクションへstatusコード404でリダイレクト
redirect_to action: 'index', status: 404
# indexアクションへstatusコード200でリダイレクト(シンボル使用)
redirect_to action: 'index', status: :ok
# indexアクションへオプション(エラーメッセージ)付きでリダイレクト
redirect_to action: 'index', alert: 'ERROR!!'
# indexアクションへオプション(通知用メッセージ)付きでリダイレクト
redirect_to ({:action => 'index'}), :notice => 'message'
# indexアクションへオプション(一時的なメッセージ)付きでリダイレクト
redirect_to action: 'index', flash: {success: 'Yes!! Success'}
redirect_to Modelオブジェクト
こんな感じのroutesの時
$ rake routes(or bundle exec rake routes)
…
model GET /users/:id(.:format) users#show
…
これが疑問だった
users_controller.rb
redirect_to @user
以下と挙動が一緒っぽい
redirect_to "/users/#{@user.id}" # 条件付き(後述)
or
redirect_to user_url(id: @user.to_param)
or
redirect_to user_url(id: @user.id)
to_paramsメソッド
Modelオブジェクトのto_paramメソッドは基本idを返す(オーバーライドしてid以外を返すのもよくあるらしい)
注意その1:Modelオブジェクトが返すURL?はuser_url(〇〇)のやつで"/users/#{@user.id}"ではない
上記では redirect_to "/usrs/#{@user.id}"
と一緒の挙動するとかある。
しかし、 config/routes.rb
で resources
を使用している場合だけ…っぽい。
resources
を使用せずに1つ1つ指定していて、usr_urlがないならできない。
undefined method `user_url' ...
的な感じで怒られる(た)。
注意その2:redirect_toでPOSTはできない
だからRailsチュートリアルではshowメソッドをPOSTにしないで、before_actionで工夫を加えていたのかなぁと解釈
追記
以下のような引数の時で、チュートリアルにもある redirect_back_or(default)
を実装したい
app/controller/sessions_controller.rb
#…(略
redirect_to controller: :users, action: :show, id: user.id
#…(略
ソース側の引数を見ると
app/helpers/sessions_helper.rb
# File actionpack/lib/action_controller/metal/redirecting.rb, line 65
def redirect_to(options = {}, response_status = {}) #:doc:
raise ActionControllerError.new("Cannot redirect to nil!") unless options
raise AbstractController::DoubleRenderError if response_body
self.status = _extract_redirect_to_status(options, response_status)
self.location = _compute_redirect_to_location(options)
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.h(location)}\">redirected</a>.</body></html>"
end
パッと分かること
- 引数はHashが2つ(options, response_status)
- status_codeは結局2つの引数から抽出している
今まで書いてた括弧なしredirecto 〇〇, 〇〇とかはどういう風にメソッド側では見られてたか、rubyを普段から触ってる人にとっては当たり前かもしれないけど、とりあえず書いた
my_redirect.rb
def my_redirect_to(a = {}, b = {})
p a
p b
end
my_redirect_to action: 'index', status: 404
# 結果
#{:action=>"index", :status=>404}
#{}
これからわかること
- 括弧で覆われてないサンプルは全部optionsに入ってた
引数がHash1つと思って、以下の様なコードにすると怒られる(た)
怒られる例
redirect_to {controller: :users, action: :show, id: user.id}
怒られない例
redirect_to {controller: :users, action: :show, id: user.id}, {}
結局、 redirect_back_or(default)
メソッドの実装はどうなるか
sessions_controller.rb
# 変更前
redirect_to controller: :users, action: :show, id: user.id
# 変更後
redirect_back_or controller: :users, action: :show, id: user.id
app/helpers/sessions_helper.rb
# 変更前
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
session.delete(:return_to)
end
# 変更後
def redirect_back_or(options = {}, response_status = {})
if session[:return_to]
redirect_to session[:return_to]
else
redirect_to options, response_status
end
session.delete(:return_to)
end
書いてて、「むむむ…」となるコードだった
三項演算子使った方が良かったのか迷うところ