Rails のルート定義についてです。
ルート定義の確認方法
ルート定義を確認する方法は次の2通りあります。
- ブラウザから
http://localhost:3000/rails/info/routes
にアクセス - ターミナルから
./bin/rake routes
または Rails 5 の場合./bin/rails routes
を実行
結果にはURLヘルパー、HTTPメソッド、URLパターン、コントローラ#アクションが表示され、ブラウザの方が検索できたりURLヘルパーを切り替えたりすることができます。
resourcesメソッド
Rails では原則として RESTful なインターフェースに沿って設計をするのが基本です。REST では HTTPメソッドの GET, POST, PATCH, DELETE で CRUD ( Create, Read, Update, Delete ) を表現します。
routes.rb にresources :users
と定義すると以下のようなURLとアクションがマッピングされ、アクションは UsersController のメソッドに対応付けられています。
URL | アクション | HTTPメソッド | パスプレフィックス |
---|---|---|---|
/users(.:format) | users#index | GET | users |
/users/:id(.:format) | users#show | GET | user_path(id) |
/users/new(.:format) | users#new | GET | new_user_path |
/users(.:format) | users#create | POST | - |
/users/:id/edit(.:format) | users#edit | GET | edit_user_path(id) |
/users/:id(.:format) | users#update | PATCH | - |
/users/:id(.:format) | users#destroy | DELETE | - |
復数のリソースを定義する場合はresources :users, :books, :authors
のように記述します。
ちなみにrake routes
コマンドを実行すると Update アクションにおいてPUT
メソッドも表示されていますが、昔の仕様が残っているだけであり、現在においてはPATCH
が推奨されています。
Riding Rails: Edge Rails: PATCH is the new primary HTTP method for updates
単一のリソースを定義
resources
メソッドは復数のリソースを対象とするのに対してresource
メソッドを使うことで単一のリソースを対象としたルート定義もできます。
主な違いは単一のリソースであるため index アクションが無い事と、show, edit, delete で :id パラメータを要求しない点です。
resource :config
パスとURLヘルパー
_path
ヘルパーの場合は相対パスを返すのに対して、_url
ヘルパーは絶対URLを返します。/users/:id
の GET メソッドであれば以下の通りです。
user_path(@user) # /users/1 user_url(@user) # http://localhost:3000/users/1
only/exceptオプション
resources
メソッドを使用するとリソースに対応する CRUD のルートが自動で定義されます。そのため実際には不要なルートがある場合にはonly
やexcept
オプションを使用して無効化しておきます。only
が有効なアクションを表し、except
が無効なアクションを表します。以下の例は同じ意味です。
resources :users, only: [:index, :show] resources :users, except: [:create, :new, :edit, :update, :destroy]
constraintsオプション
constraints
オプションを使うとルートパラメータに対して制約条件を付ける事ができます。パラメータ名: 正規表現
の形式で指定して下さい。
resources :users, constraints: { id: /\d+/ }
formatオプション
resources
メソッドで定義されたすべてのルートはデフォルトで(.:format)
が付与されています。これによって復数の拡張子の形式で出力フォーマットを指定できますが、復数のフォーマットに対応したくない場合は次のようにします。ちなみに(.:format)
のデフォルトは.html
です。
resources :users, format: false
controllers/asオプション
resources
メソッドはデフォルトで指定されたリソース名をもとに対応するコントローラを決定し、URLヘルパーを生成します。そのためcontroller
やas
オプションを仕様することで変更することが可能です。
resources :users, controller: :member # MemberControllerがマッピングされる resources :users, as: :member # members_path, new_member_path のヘルパーになる
namespace/scopeブロック
モジュール配下のコントローラをマッピングするにはnamespace
ブロックを使用します。モジュール配下というのはrails g controller Admin::Users
のようにコントローラを生成した場合、controllers/admin
フォルダ配下に作成されるコントローラのことです。
このようなコントローラに対してルート定義をするには、以下のようにnamespace
でモジュール名、ブロック配下にリソースを定義して下さい。リソースは復数でも問題ありません。
namespace :admin do resources :users end ... admin_users GET /admin/users(.:format) admin/users#index
この場合、URLには/admin/users/:id
のように admin が含まれてしまいますが、scope
ブロックを使うことによってURLをモジュールを使用しない状態と同じように扱えます。
scope module: :admin do resources :users end ... users GET /users(.:format) admin/users#index
上記とは逆にモジュールに属さないコントローラに対してURLにプレフィックスを付与したい場合はmodule:
指定なしのscope
ブロックを使用します。
scope :hoge do resources :books end ... books GET /hoge/books(.:format) books#index
collection/memberブロック
resources
メソッドで生成されるルート定義は固定ですが、必要に応じて別のアクションを追加することができます。collection
ブロックは復数のオブジェクトを扱うアクションに対して、member
ブロックは単一のオブジェクトを扱うアクションに対して、それぞれ利用します。
以下のルーティングはGETリクエストの/users/search
パスを認識し、リクエストを UsersController の search アクションにマッピングします。復数オブジェクトを扱うため :id パラメータは含みません。
resources :users do collection do get 'search' end end ... search_users GET /users/search(.:format) users#search
member
の場合は以下のように記述することでGETリクエストの/books/:id/author
パスを認識し、BooksController の author アクションにマッピングします。単一オブジェクトのため id 値はparams[:id]
で渡されます。
resources :books do member do get 'author' end end ... author_book GET /books/:id/author(.:format) books#author
ブロック配下のアクションがひとつである場合は、on
パラメータを使ってシンプルに記述できます。
resources :xxxx do get 'search', on: :collection get 'author', on: :member end
resourcesメソッドのネスト
リソース同士の親子関係をURLとして表現したい場合はresources
メソッドのネストを使用します。親のリソースは :id が変わっているのがわかります。
resources :books do resources :reviews end
book_reviews GET /books/:book_id/reviews(.:format) reviews#index POST /books/:book_id/reviews(.:format) reviews#create new_book_review GET /books/:book_id/reviews/new(.:format) reviews#new edit_book_review GET /books/:book_id/reviews/:id/edit(.:format) reviews#edit book_review GET /books/:book_id/reviews/:id(.:format) reviews#show PATCH /books/:book_id/reviews/:id(.:format) reviews#update PUT /books/:book_id/reviews/:id(.:format) reviews#update DELETE /books/:book_id/reviews/:id(.:format) reviews#destroy
shallowオプション
resources
メソッドのネストを使用した時にshallow
オプションを付けることによって、:id パラメータを受け取るアクションはネストされない浅いURLが生成されるようになります。
resources :books do resources :reviews, shallow: true end
book_reviews GET /books/:book_id/reviews(.:format) reviews#index POST /books/:book_id/reviews(.:format) reviews#create new_book_review GET /books/:book_id/reviews/new(.:format) reviews#new edit_review GET /reviews/:id/edit(.:format) reviews#edit review GET /reviews/:id(.:format) reviews#show PATCH /reviews/:id(.:format) reviews#update PUT /reviews/:id(.:format) reviews#update DELETE /reviews/:id(.:format) reviews#destroy
scope メソッドとshallow_path
オプションを併用することで浅いURLにプレフィックスを付与することができます。
scope shallow_path: :hoge do resources :books do resources :reviews, shallow: true end end ... review GET /hoge/reviews/:id(.:format) reviews#show
concernメソッドとオプション
concern
メソッドを利用することで、復数のルート定義で共通する内容を切り出せます。
concern :additional do get :unapproval, on: :collection get :draft, on: :member end resources :reviews, concerns: :additional resources :users, concerns: :additional