アプリの例
例えば、投稿の詳細ページから編集できるアプリを考えよう。
コントローラー、ビューの記述は以下の通りである。
#post_controller.rb
def edit
@post= Post.find(params[:id])
end
def show
@post= Post.find(params[:id])
end
#show.html.erb
<%= link_to "編集する", edit_post_path(@post)%>
なぜパスに引数を記述する必要があるのか?
どの投稿(post)の編集ページに遷移するかを明示するためである。
rails routesを実行すると以下のように表示される。
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
editのURIを見ると、「/posts/:id/edit(.:format) 」と記載されている。
つまり、idの情報が必要なのである。
直感的にも、「どの投稿を編集ページなのか」を特定するためにはid情報が必要だということが分かるはずである。
edit_post_path(@post)は、「edit_post_pathに遷移してください。対象のpostはコントローラー(のshowアクション)で定義した@postです。」という意味である。
idを引き渡すための記述なので、より細かく記述するなら、「edit_post_path(@post.id)」となる。(@postでも良い理由は、@postの情報からrailsが勝手にid情報を見つけてくれるからである。)
引数がなくても遷移できるんだが?
今回の例のアプリでは、引数を記述しなくても適切に編集ページに遷移できる。
なぜ引数がなくても特定のpostの編集ページに遷移できるのだろうか。
それは、詳細ページ(show.html.erb)の時点でURIにidが含まれているからである。
現在のURIに含まれているidを元に、railsが自動的に判断している。
よって、異なる対象に移動する場合は、引数がないとエラーが発生する。
エラー例
#投稿したpostの情報
id=5 content=”5番目の投稿です’ user_id=1
#投稿者の情報
id=1 nickname=”一番目太郎’
投稿(post)のidは5であり、投稿者(user)のidは1である。
投稿の詳細ページから、「一番目太郎の投稿一覧」に遷移したいとする。
#パスの例
<%= link_to "by #{@post.user.nickname}", user_path%>
引数を記述していないので、現在のパス(投稿の詳細ページのURI)に含まれている「id=5」という情報を元に遷移が行われる。
結果、「id=5のユーザーの投稿一覧」を表示しようとしてエラーが発生する。
(user does”t exist id=5 などのエラーが出る。)
投稿者の投稿一覧へのパス
以下のようになる。
<%= link_to "by #{@post.user.nickname}", user_path(@post.user)%>
流れとしては、
「post_controllerのshowアクション」
↓
「posts/show.html.erb」
↓
「users/show.html.erb」
となる。
スタート地点はpostコントローラーである。
よって、userの情報もpostを起点として手に入れることが好ましい。
故に、引数はコントローラーに定義した@postを起点として、「@post.user」としている。