LoginSignup
22
21

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-09-05

はじめに

私が業務で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

22
21
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
21