はじめに
この記事では、Rails(4.2系)のルーティングの「namespaceとmodule」と「resourceとresources」と「memberとcollection」に関して説明したいと思います。
これは、最近Railsのルーティングをがっつり触る機会があり、その際の知見を記事にしたものです。
rake routesの表示の違いを述べるだけでなく、どのような状況で使うのかという説明も可能な限り記載しました。
前提
adminとstaffがいるシステムを考えます。業務システムではよく出てくる登場人物だと思いますが、管理者(admin)がスタッフ(staff)を操作(CRUD)できるものとします。
本編
namespaceとmodule
namespace
adminがstaffを操作する機能に必要なルーティングは以下のようになります。
namespace :admin do
resources :staffs
end
$ rake routes | grep admin
admin_staffs GET /admin/staffs(.:format) admin/staffs#index
POST /admin/staffs(.:format) admin/staffs#create
new_admin_staff GET /admin/staffs/new(.:format) admin/staffs#new
edit_admin_staff GET /admin/staffs/:id/edit(.:format) admin/staffs#edit
admin_staff GET /admin/staffs/:id(.:format) admin/staffs#show
PATCH /admin/staffs/:id(.:format) admin/staffs#update
PUT /admin/staffs/:id(.:format) admin/staffs#update
DELETE /admin/staffs/:id(.:format) admin/staffs#destroy
module
ここで、違いを把握するためnamespaceの代わりにmoduleを使ってみましょう。
resources :staffs, module: 'admin'
$ rake routes | grep admin
staffs GET /staffs(.:format) admin/staffs#index
POST /staffs(.:format) admin/staffs#create
new_staff GET /staffs/new(.:format) admin/staffs#new
edit_staff GET /staffs/:id/edit(.:format) admin/staffs#edit
GET /staffs/:id(.:format) admin/staffs#show
PATCH /staffs/:id(.:format) admin/staffs#update
PUT /staffs/:id(.:format) admin/staffs#update
DELETE /staffs/:id(.:format) admin/staffs#destroy
見比べると、staffのindexページにアクセスするためのURIが、
namespaceを指定した場合は/admin/staffs(.:format)
となっており、一方moduleを指定した場合は/staffs(.:format)
となっています。
コメント
moduleの用途としては以下の記事をご覧ください。
Railsで多対多モデルを実装する場合のルーティング(moduleオプションの使い方)
また、調べてみるとnamespaceとmoduleの他にscopeがあるようです。詳しくは以下で詳細な説明が載っているのでご覧ください。
routeのmoduleとnamespaceとscopeの違い
resourceとresources
今度は、「namespaceとmodule」で触れた仕様に加えて、adminがstaffのパスワードを変更できる仕様を考えます。
resource
パスワード変更は通常のstaff#editとは別のフォームで実装することを考えます(なお、updateアクションに関してはstaff#updateを呼び出すべきですが、そちらに関してはviewに記述するため省略します)。
この場合、ユーザー1人に対してパスワードが1つ存在するので、resouceを使用します。
namespace :admin do
resources :staffs do
resource :password, only: [ :edit ]
end
end
$ rake routes | grep admin
edit_admin_staff_password GET /admin/staffs/:staff_id/password/edit(.:format) admin/passwords#edit
~以下略~
resources
一方、比較のために上記をresourcesを使用し記述すると以下のようになります。
namespace :admin do
resources :staffs do
resources :password, only: [ :edit ]
end
end
$ rake routes | grep admin
edit_admin_staff_password GET /admin/staffs/:staff_id/password/:id/edit(.:format) admin/password#edit
~以下略~
URIが/admin/staffs/:staff_id/password/:id/edit(.:format)
となり、staffにパスワードが複数紐付いているようなケースのURIとなってしまい不適です。
memberとcollection
次は、単純なCRUD操作以外の処理を追加していきましょう。CRUD内に適切なメソッドがないケースではmemberもしくはcollectionを使います。
まず、管理者がスタッフページをカスタマイズするというケースを考えましょう(例えば、見やすくするために部ごとにスタッフページのレイアウトを変えたいというケースです)。
member
スタッフではなくスタッフページへの操作なので、単純にstaffのeditやupdateを使用せずmemberにてpage_customメソッドを追加します。
namespace :admin do
resources :staffs, module: 'staff_magagement' do
member do
get :page_custom
end
end
end
$ rake routes | grep page_custom
page_custom_admin_staff GET /admin/staffs/:id/page_custom(.:format) admin/staff_magagement/staffs#page_custom
admin_staffs GET /admin/staffs(.:format) admin/staff_magagement/staffs#index
POST /admin/staffs(.:format) admin/staff_magagement/staffs#create
new_admin_staff GET /admin/staffs/new(.:format) admin/staff_magagement/staffs#new
edit_admin_staff GET /admin/staffs/:id/edit(.:format) admin/staff_magagement/staffs#edit
admin_staff GET /admin/staffs/:id(.:format) admin/staff_magagement/staffs#show
PATCH /admin/staffs/:id(.:format) admin/staff_magagement/staffs#update
PUT /admin/staffs/:id(.:format) admin/staff_magagement/staffs#update
DELETE /admin/staffs/:id(.:format) admin/staff_magagement/staffs#destroy
collection
今度は、staffを検索する機能(search)を実現するルーティングです。searchアクションはstaff全体への操作でありidを渡す必要がないので、collectionを使用します。
namespace :admin do
resources :staffs, module: 'staff_magagement' do
collection do
get :search
end
end
end
$ rake routes | grep search
search_admin_staffs GET /admin/staffs/search(.:format) admin/staff_magagement/staffs#search
最後に
誤りやご意見ありましたらご指摘いただけると嬉しいです。
##参考
http://qiita.com/ebihara99999/items/6e49830f8fd03a5a40dd
http://qiita.com/blueplanet/items/522cc8364f6cf189ecad