78
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Railsルーティング:「namespaceとmodule」「resourceとresources」「memberとcollection」

はじめに

この記事では、Rails(4.2系)のルーティングの「namespaceとmodule」と「resourceとresources」と「memberとcollection」に関して説明したいと思います。
これは、最近Railsのルーティングをがっつり触る機会があり、その際の知見を記事にしたものです。
rake routesの表示の違いを述べるだけでなく、どのような状況で使うのかという説明も可能な限り記載しました。

前提

adminとstaffがいるシステムを考えます。業務システムではよく出てくる登場人物だと思いますが、管理者(admin)がスタッフ(staff)を操作(CRUD)できるものとします。

本編

namespaceとmodule

namespace

adminがstaffを操作する機能に必要なルーティングは以下のようになります。

routes.rb
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を使ってみましょう。

routes.rb
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を使用します。

routes.rb
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を使用し記述すると以下のようになります。

routes.rb
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メソッドを追加します。

routes.rb
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を使用します。

routes.rb
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

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
78
Help us understand the problem. What are the problem?