Rails でリンクパスを生成する方法色々・・とRails console で 生成される path を確認したい時

# Polymorphic URL 使うといいよ！という話

参考ページ：
[Rails Best Practices - Generate polymorphic url](http://rails-bestpractices.com/posts/2010/09/23/generate-polymorphic-url/)

Rails初学者が出会うpathの生成ヘルパーから、一歩進んだパス生成方法について、グダグダと書く。

## 前提

### 例に使用するScaffold

```
$ ./bin/rails g scaffold Question title:string content:text
$ ./bin/rails g scaffold Answer content:text question:references
```

Question has_many Answers.
Answer belongs_to Question.

とする。

``` app/models/question.rb
class Question < ActiveRecord::Base
  has_many :answers
end
```

``` app/models/answer.rb
class Answer < ActiveRecord::Base
  belongs_to :question
end
```

### Routingは標準REST

親子関係があるので、ルーティングをネスト
（この方がネストしたリンクパスを生成する方法も一緒に書けるので）

``` config/routes.rb
resources :questions do
  resources :answers
end
```

### 出来上がったルーティング

```
$ ./bin/rake routes
```

                  Prefix Verb   URI Pattern                                        Controller#Action
        question_answers GET    /questions/:question_id/answers(.:format)          answers#index
                         POST   /questions/:question_id/answers(.:format)          answers#create
     new_question_answer GET    /questions/:question_id/answers/new(.:format)      answers#new
    edit_question_answer GET    /questions/:question_id/answers/:id/edit(.:format) answers#edit
         question_answer GET    /questions/:question_id/answers/:id(.:format)      answers#show
                         PATCH  /questions/:question_id/answers/:id(.:format)      answers#update
                         PUT    /questions/:question_id/answers/:id(.:format)      answers#update
                         DELETE /questions/:question_id/answers/:id(.:format)      answers#destroy
               questions GET    /questions(.:format)                               questions#index
                         POST   /questions(.:format)                               questions#create
            new_question GET    /questions/new(.:format)                           questions#new
           edit_question GET    /questions/:id/edit(.:format)                      questions#edit
                question GET    /questions/:id(.:format)                           questions#show
                         PATCH  /questions/:id(.:format)                           questions#update
                         PUT    /questions/:id(.:format)                           questions#update
                         DELETE /questions/:id(.:format)                           questions#destroy


## Railsでリンクパスを生成する方法

### XXX_path 方式

初心者的には一番最初に出会う王道的パスの生成方法

上記 ``` rake routes ``` で出てきた Prefix を XXX に入れれば良い。

例： Question#showへのパス

```
question GET    /questions/:id(.:format)                           questions#show
```

なので question_path :idがあるのでオブジェクトを引数に渡す

```app/views/questions/index.html.haml
= link_to @question.title, question_path(@question)
```

#### Rails consoleで合ってるか確認

```
$ ./bin/rails c
pry> @question = Question.first
pry> app.question_path(@question)
=> "/questions/1"
```

### ネストしてる場合

例： Answer#showへのパス

```
question_answer GET    /questions/:question_id/answers/:id(.:format)      answers#show
```

``` app/views/answers/index.html.haml
%ul
  - @question.answers.each do |answer|
    %li= link_to answer.id, question_answer_path(@question, answer)
```

#### Rails consoleで合ってるか確認

```
$ ./bin/rails c
pry> @question = Question.first
pry> answer = @question.answers.first
pry> app.question_answer_path(@question, answer)
=> "/questions/1/answers/1"
```

## polymorphic_path 方式

モデルから該当のパスをジェネレートさせる方法 polymorphic_path で書きなおしてみる。

```app/views/questions/index.html.haml
= link_to @question.title, @question
```

モデルから類推してちゃんとパスを生成してくれる。

#### Rails consoleで合ってるか確認
appにいきなりオブジェクトを渡してもダメなので、consoleでは明示的に ```polymorphic_path``` と書く。

```
$ ./bin/rails c
pry> @question = Question.first
pry> app.polymorphic_path(@question)
=> "/questions/1"
```

### ネストしてる場合

polymorphic_path で複数モデルを渡す場合、配列として渡す。

``` app/views/answers/index.html.haml
%ul
  - @question.answers.each do |answer|
    %li= link_to @answer.id, [ @question, answer ]
```

#### Rails consoleで合ってるか確認

```
$ ./bin/rails c
pry> @question = Question.first
pry> answer = @question.answers.first
pry> app.polymorphic_path([@question, answer])
=> "/questions/1/answers/1"
```

配列で渡さないと ``` ArgumentError : wrong number of arguments (1 for 0) ``` になってしまう。

## モデルが不要なパスを polymorphic_url で生成する方法

newとかindexみたいに、モデルが不要な場合

### XXX_path方式

```
= link_to '新しく質問する', new_question_path
```

### polymorphic_path 方式

シンボルで指定する。

以下の３つの方法は、どれも同じパスを生成できる。

```
= link_to '新しく質問する', [ :new, :question ]
```

```
= link_to '新しく質問する', polymorphic_path([ :new, :question ])
```

```
= link_to '新しく質問する', new_polymorphic_path(:question)
```

### ネストしてる場合

```
= link_to '新しく回答する', [ :new, @question, :answer ]
```

```
= link_to '新しく回答する', polymorphic_path([ :new, @question, :answer ])
```

```
= link_to '新しく回答する', new_polymorphic_path([ @question, :answer ])
```