Edited at

Railsのルーティングをカスタマイズしたときのメモ

More than 1 year has passed since last update.


はじめに

私が業務でRailsアプリケーションのルーティングをカスタマイズ・整理したときのメモです。

Ruby on Rails Guidesに書いてある中で、これ使うぞと思うものを自分なりにピックアップしました。

最近Railsの開発をしていないので、もっといい方法をご存知の方がいらっしゃったら声を大にして教えていただけると嬉しいです。


目次


  • 基本形を自動生成しないで定義したいとき

  • 階層構造をもったURLを定義したいとき

  • オリジナルのActionをちょい足ししたいとき

  • 複数のControllerにオリジナルのActionをちょい足ししたいとき


基本形を自動生成しないで定義したいとき

CRUD全てを定義したいときは以下のように書けばよいです。

自動生成しても同じ内容がroutes.rbに定義されます。

resources :book_shops

とはいえ、手動でルーティングを定義するときというのは、特定のActionへのルーティングだけを定義したいときだと思います。例えば、indexとshowしか使わないとか。そんな時はonly: [:許可するアクション]と書けばOKです。

resources :book_shops, only: [:index, :show]

# 以下のように定義してもよいですが、面倒だと思います。
# get 'books', to 'books#index'
# get 'books/:id', to 'books#show'


階層構造をもったURLを定義したいとき

has-manyなどリレーションのあるModelについて実装をするときに起こりうると思います。

例えば、/book_shop/28/booksにアクセスさせて、IDが28番である本屋の蔵書一覧がわかるとか。

resources :book_shops do

resources : books
end


@scivola さんよりご指摘いただき、以下の表の内容を修正いたしました。


HTTP methods
Path
Controller#Action

GET
book_shops/:book_shop_id/books
book_shop#index

GET
book_shops/:book_shop_id/books/new
book_shop#new

POST
book_shops/:book_shop_id/books
book_shop#create

GET
book_shops/:book_shop_id/books/:id
book_shop#show

GET
book_shops/:book_shop_id/books/:id/edit
book_shop#edit

PUT/PATCH
book_shops/:book_shop_id/books/:id
book_shop#update

DELETE
book_shops/:book_shop_id/books/:id
book_shop#destroy

ネストさせる場合も、特定のActionへのルーティングのみ定義することができます。

後ろにonly: [:許可するアクション]と書けばOKです。

resources :book_shops do

resources : books, only: [:index, :show]
end


オリジナルのActionをちょい足ししたいとき


/controller/:id/action形式

例えば、指定した書籍をダウンロードするActionへのルーティングを定義するには、以下のように定義します。

resources :books do

member do
post 'download'
# post 'download', on: :memberでもOK
do

基本形に同じくpost 'books/:id/download', to 'book#download'と任意の場所に定義してもよいですが、私は推奨しません。

同じControllerに対するルーティングは1か所に書いたほうがメンテナンスしやすいからです。バラバラの場所に書くと、何が定義されていて何が定義されていないのか管理するのが大変になります。


/controller/action形式

例えば、書籍の一覧に対して検索をするActionへのルーティングを定義するには、以下のように定義します。

resources :books do

collection do
get 'search'
# get 'search', on: :collectionでもOK
do


複数のControllerにオリジナルのActionをちょい足ししたいとき

検索用のルーティングを用意したものの、そのActionって色んなところで使うのだけれどもという場合ですね。

ルーティングが一つだとうま味が少ないかと思いますので、以下のActionを追加してみたいと思います。


  • 作成確認画面:new_confirm

  • 編集確認画面:edit_confirm

  • 削除確認画面:delete_confirm

確認画面を足すとかあるあるですよね(たぶん)。

今までの知識でbook_shop_controllerとbook_controllerにルーティングを追加すると以下のようになるはずです。

resources :book_shops do

post 'new_confirm', on: :collection
member do
post 'edit_confirm'
post 'delete_confirm'
end
end

resources :books do
post 'new_confirm', on: :collection
member do
post 'edit_confirm'
post 'delete_confirm'
end
end

別にこれでもいんですけども、少し冗長ですよね。

今は2つしかないからよいですが、あとから機能追加で数十個もControllerを足すとなれば、routes.rbは地獄絵図と化すでしょう。

concernを使えば、上のような冗長さを解決できます。

resources :book_shops, concerns: :confirmable

resources :books, concerns: :confirmable

concern :confirmable do
post 'new_confirm', on: :collection
member do
post 'edit_confirm'
post 'delete_confirm'
end
end

最高にイケてるルーティングになったような気がしますね(自画自賛)。


補足

本当はControllerをサブディレクトリに分ける際のお話もしたかったのですが

ここまででも話が長くなってしまったので割愛させていただきます。


参考ページ

Ruby on Rails Guides