はじめに
actionを追加する時のルーティングの設定について、メンバー(member) とコレクション(collection)について調べたことをまとめています。
※actionを追加時のcontrollerやviewの設定については割愛しています。
やりたかったこと
hogeというactionをarticle controllerに追加したい。routesは、こうなる予定。
$ rails routes | grep hoge
=> hoge_article GET /articles/:id/hoge(.:format)
articles#hoge
ちなみに編集前のroutesはこちら。
routes.rb
Rails.application.routes.draw do
resources :articles do
resources :comments
end
root 'welcome#index'
end
困ったこと
article
の中にget :hoge
を書いてOKと思いきや、意図と異なるルーティングになってしまった。
routes.rb
Rails.application.routes.draw do
resources :articles do
resources :comments
get :hoge
end
root 'welcome#index'
end
$ rails routes | grep hoge
=> article_hoge GET /articles/:article_id/hoge(.:format)
articles#hoge
原因
デフォルトで作成される7つのaction(index,new,create,show,edit,update,destroy)以外のルーティングを追加する場合は、適切なルーティングブロックの追加が必要でした。
メンバールーティングとコレクションルーティング
適切なルーティングブロックの追加=メンバールーティングまたは、コレクションルーティングをリソースブロックに追加します。
ざっくりとこのような機能を生成してくれます。
- GETリクエストとパスを認識
- リクエストを、リソースブロックで指定したコントローラのコレクションルーティングで指定したアクションにルーティング
- パスに対応した
xxxx_url
ヘルパー、xxxx_path
を作成
GETリクエストとパスを認識
の挙動に大きな違いがあります。
メンバールーティング
memberブロックを追加すると
- GETリクエストとそれに伴う/articles/[:id]/hogeを認識する
- リソースid値をparams[:id]に渡す
routes.rb
resources :articles do
member do
get :hoge
end
end
コレクションルーティング
collectionブロックを追加すると
- GETリクエスト+/articles/hogeなどの (idを伴わない) パスを認識する
routes.rb
resources :articles do
collection do
get :hoge
end
end
実際に修正
memberブロックを追加
idを認識する必要があったため、メンバールーティングを用いてroutesを修正。
routes.rb
Rails.application.routes.draw do
resources :articles do
resources :comments
member do
get :hoge
end
end
root 'welcome#index'
end
on:オプションを使用して更にソースをすっきりさせる
メンバールーティングまたは、コレクションルーティングが一つしかない場合は、on:
オプションを利用することができる。
routes.rb
Rails.application.routes.draw do
resources :articles do
resources :comments
get :hoge, on: :member
end
root 'welcome#index'
end
意図したルーティングを実現することが出来ました。
$ rails routes | grep hoge
=> hoge_article GET /articles/:id/hoge(.:format)
articles#hoge