Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

Polymorphic URL 使うといいよ!という話

参考ページ:
Rails Best Practices - 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 方式

シンボルで指定する。

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

= 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 ])
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした