cre8cre8
AskMe♥

RESTfulにするためRailsのルーティングをresources,namespace,scopeだけで頑張る

getやpost使うのは邪道派の皆様こんばんわ。たくみです。
今回はRailsでアプリ作る上で宗教戦争にも発展しかねないルーティングのことを書こうと思います。
特に私が大好きな resources / namespace / scope あたりを一生懸命解説しますね。

RESTfulなら俺に任せな![resources編]

resourcesはRESTfulなルーティングを生成します。
scaffoldしたときにroutes.rbに自動でよく追加されるやつですね。
具体的なURLにすると下記のようになります。

routes.rb
1resources :worlds
2
3#    Prefix Verb   URI Pattern                Controller#Action
4#     worlds GET    /worlds(.:format)          worlds#index
5#            POST   /worlds(.:format)          worlds#create
6#  new_world GET    /worlds/new(.:format)      worlds#new
7# edit_world GET    /worlds/:id/edit(.:format) worlds#edit
8#      world GET    /worlds/:id(.:format)      worlds#show
9#            PATCH  /worlds/:id(.:format)      worlds#update
10#            PUT    /worlds/:id(.:format)      worlds#update
11#            DELETE /worlds/:id(.:format)      worlds#destroy

GET/POST/PUT(PATCH)/DELETE があるので参照、作成、更新、削除全部できます。
いわゆるRESTfulなURLをたった1行書くだけで全部書いてくれます。便利ですね。

見に行くコントローラもわかりやすく、上記のサンプルの場合は WorldsController を見に行きます。
シンプルなRailsアプリケーションの場合はroutes.rbにresourcesしか書かかれてないことが多かったりもします。

そんなresourcesさんもちょっとした弱点があります。
例えば、URLをもっと複雑にしたい場合や、コントローラがめちゃくちゃ多くなってディレクトリに分けたいときなど…
そんなときには頼れる仲間、namespaceさんとscopeさんを使いましょう!

コントローラが多い?ふふふ…私の出番ですね(イケボ)[namespace編]

例えば、scaffoldで rails g scaffold my/role と実行したときにroutes.rbに namespace がでてきます。

routes.rb
1Rails.application.routes.draw do
2  namespace :my do
3    resources :roles
4  end
5#       Prefix Verb   URI Pattern                  Controller#Action
6#     my_roles GET    /my/roles(.:format)          my/roles#index
7#              POST   /my/roles(.:format)          my/roles#create
8#  new_my_role GET    /my/roles/new(.:format)      my/roles#new
9# edit_my_role GET    /my/roles/:id/edit(.:format) my/roles#edit
10#      my_role GET    /my/roles/:id(.:format)      my/roles#show
11#              PATCH  /my/roles/:id(.:format)      my/roles#update
12#              PUT    /my/roles/:id(.:format)      my/roles#update
13#              DELETE /my/roles/:id(.:format)      my/roles#destroy
14
15end
namespaceを使うとディレクトリ(モジュール)に分けられたコントローラにアクセスすることができます。
具体的には app/controllers/my/roles_controller.rb を見に行くようになります。
URLとコントローラのディレクトリが一致するので、たくさんコントローラがあっても整理することができますね。
namespaceさまさまです。

ふぇぇ…URLをもっと自由にしたいよぉ…[scope編]

namespaceの便利さはわかっていただいたと思いますが、コントローラ数が2、3個のときに
ディレクトリに分けるのも手間がかかりますよね。
特に一度、scaffoldで作ったあとにURLだけ変更したくなったとかなると地獄級です。
ですが、さすが私達のRails!こういうことも見越して(?)か便利なscopeというものがあります!

では、一番最初に作った worlds のURLを oh/my/worlds にしてみましょう。

routes.rb
1Rails.application.routes.draw do
2  scope :oh do
3    scope :my do
4      resources :worlds
5    end
6  end
7
8#     Prefix Verb   URI Pattern                      Controller#Action
9#     worlds GET    /oh/my/worlds(.:format)          worlds#index
10#            POST   /oh/my/worlds(.:format)          worlds#create
11#  new_world GET    /oh/my/worlds/new(.:format)      worlds#new
12# edit_world GET    /oh/my/worlds/:id/edit(.:format) worlds#edit
13#      world GET    /oh/my/worlds/:id(.:format)      worlds#show
14#            PATCH  /oh/my/worlds/:id(.:format)      worlds#update
15#            PUT    /oh/my/worlds/:id(.:format)      worlds#update
16#            DELETE /oh/my/worlds/:id(.:format)      worlds#destroy
17
18end

scopeで囲む参照先のコントローラは app/controllers/worlds_controller.rb のままで
URLを /oh/my/worlds にできましたね。

まとめ

resources, namespace, scope を使うと、RESTfulでもURLを自由に構築することができましたね。
それでは、おさらいしていきましょう。
- RESTfulなURLを作るには resources を用いる
- コントローラのパスとURLを一致させたいときは namespace が便利
- URLを柔軟にしたい場合は scope を使うとコントローラを変更せずにURLを変えられる

Railsのルーティングには他にも便利な機能がたくさんあります。
RESTfulな設計では使いづらいような場合に対応できる機能(get,post,matchなど)もありますので、
そのうち解説記事を書こうと思います。

(2016/12/08追記:書いちゃいました!) get,post,delete,putそしてmatchでルーティングを頑張る

≪ 前の記事
これさえ覚えれば大丈夫!scaffoldをまとめてみた
次の記事 ≫
get,post,delete,putそしてmatchでルーティングを頑張る

いいねやコメントを送っていただけると中の人がしっぽ振って大喜びします♪

あなたへのおすすめの記事