Rails
RubyOnRails
Action追加

action追加とメンバー(member) とコレクション(collection)

はじめに

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

参照サイト

Rails のルーティング - Ruby on Rails ガイド