redirect_to の引数とかのメモ


## 基本

```ruby:ドキュメントにある使用方法(よくある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
…
```

#### これが疑問だった
```ruby:users_controller.rb
redirect_to @user
```

```ruby:以下と挙動が一緒っぽい
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以外を返すのもよくあるらしい)

- [URLのidの部分にid以外のものを指定(to_param)](http://railsdoc.com/references/to_param)


#### 注意その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でPOSTリクエストではリダイレクトできないことへの対応](http://easyramble.com/cannot-post-redirect-on-rails.html)
- [redirect_to using POST in rails]()

だからRailsチュートリアルではshowメソッドをPOSTにしないで、before_actionで工夫を加えていたのかなぁと解釈

## 追記
以下のような引数の時で、チュートリアルにもある `redirect_back_or(default)` を実装したい

```ruby:app/controller/sessions_controller.rb
#…(略
redirect_to controller: :users, action: :show, id: user.id
#…(略
```

ソース側の引数を見ると

```ruby: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を普段から触ってる人にとっては当たり前かもしれないけど、とりあえず書いた

```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つと思って、以下の様なコードにすると怒られる(た)

```ruby:怒られる例
redirect_to {controller: :users, action: :show, id: user.id}
```

```ruby:怒られない例
redirect_to {controller: :users, action: :show, id: user.id}, {}
```

#### 結局、 `redirect_back_or(default)` メソッドの実装はどうなるか

```ruby: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
```

書いてて、「むむむ…」となるコードだった
三項演算子使った方が良かったのか迷うところ

## 参考
- [redirect_to @model て何よ](http://gagapi.hatenablog.jp/entry/2013/03/16/102746)
- [redirect_to (Railsドキュメント)](http://railsdoc.com/references/redirect_to)
- [Rails チュートリアル 4.0](http://railstutorial.jp/)