まとめようと思った経緯
と思って書き始めたのが1月の中頃
何を言っているのかわからねーと思うが
気づいたら違う記事をいくつか書いて公開していた。
(いつのまにかRuby2.2.1もリリースされていた・・・)
urlを直接指定する
get '/games', to: 'games#index'
get '/games/:id', to: 'games#show'
get '/games/test', to: 'games#test', as: :test
下記のようにも書ける
get '/games' => 'games#index'
get '/games/:id' => 'games#show'
get '/games/test' => 'games#test', as: :test
resource
scaffoldを使用した際にroutes.rbに追記される
複数のroutingを作成してくれやつ
resource :users
これだけで下記のようなroutingが生成される(簡単!)
Prefix |
Verb |
URI Pattern |
Controller#Action |
users |
GET |
/users(.:format) |
users#index |
|
POST |
/users(.:format) |
users#create |
new_user |
GET |
/users/new(.:format) |
users#new |
edit_user |
GET |
/users/:id/edit(.:format) |
users#edit |
user |
GET |
/users/:id(.:format) |
users#show |
|
PATCH |
/users/:id(.:format) |
users#update |
|
PUT |
/users/:id(.:format) |
users#update |
|
DELETE |
/users/:id(.:format) |
users#destroy |
一部のroutingがいらない場合
resourceで作成されるroutingでindexとshowは必要だけどcreateいらないとかのパターンは
下記の用にonly,exceptで絞ることが可能
resource :sports, only: [:index]
resource :posts, except: [:index, :show]
向き先のcontrollerを変更
下記のようにcontrollerを指定することも可能
この場合「GET /hoge」へのリクエストが「users#index」に
resources :hoge, controller: :users
Prefix |
Verb |
URI Pattern |
Controller#Action |
hoge |
POST |
/hoge(.:format) |
users#create |
new_hoge |
GET |
/hoge/new(.:format) |
users#new |
edit_hoge |
GET |
/hoge/edit(.:format) |
users#edit |
|
GET |
/hoge(.:format) |
users#show |
|
PATCH |
/hoge(.:format) |
users#update |
|
PUT |
/hoge(.:format) |
users#update |
|
DELETE |
/hoge(.:format) |
users#destroy |
ネストしてみると・・・
resourceをネストしてみると下記のようなroutingが生成される
※結果が長くなってしまうのでonlyで絞っています。
resource :authors, only: [:index, :show, :create] do
resource :books, only: [:index, :show, :create]
end
Prefix |
Verb |
URI Pattern |
Controller#Action |
authors_books |
POST |
/authors/books(.:format) |
books#create |
|
GET |
/authors/books(.:format) |
books#show |
authors |
POST |
/authors(.:format) |
authors#create |
|
GET |
/authors(.:format) |
authors#show |
collection
resources :dogs, only: [:index, :show, :create] do
get 'test1', on: :collection
get 'test2', on: :collection
end
下記のようにも書ける
resources :dogs, only: [:index, :show, :create] do
collection do
get 'test1'
get 'test2'
end
end
Prefix |
Verb |
URI Pattern |
Controller#Action |
test1_dogs |
GET |
/dogs/test1(.:format) |
dogs#test1 |
test2_dogs |
GET |
/dogs/test2(.:format) |
dogs#test2 |
dogs |
GET |
/dogs(.:format) |
dogs#index |
|
POST |
/dogs(.:format) |
dogs#create |
dog |
GET |
/dogs/:id(.:format) |
dogs#show |
member
resources :cats do
get 'test1', on: :member
get 'test2', on: :member
end
下記のようにも書ける
resources :cats do
member do
get 'test1'
get 'test2'
end
end
Prefix |
Verb |
URI Pattern |
Controller#Action |
test1_cat |
GET |
/cats/:id/test1(.:format) |
cats#test1 |
test2_cat |
GET |
/cats/:id/test2(.:format) |
cats#test2 |
cats |
GET |
/cats(.:format) |
cats#index |
|
POST |
/cats(.:format) |
cats#create |
new_cat |
GET |
/cats/new(.:format) |
cats#new |
edit_cat |
GET |
/cats/:id/edit(.:format) |
cats#edit |
cat |
GET |
/cats/:id(.:format) |
cats#show |
|
PATCH |
/cats/:id(.:format) |
cats#update |
|
PUT |
/cats/:id(.:format) |
cats#update |
|
DELETE |
/cats/:id(.:format) |
cats#destroy |
new
上記のcollection, memberの他にnewも指定可能
resources :companies, only: [:index, :show, :create] do
get 'test1', on: :new
get 'test2', on: :new
end
下記のようにも書ける
resources :companies, only: [:index, :show, :create] do
new do
get 'test1'
get 'test2'
end
end
Prefix |
Verb |
URI Pattern |
Controller#Action |
test1_new_company |
GET |
/companies/new/test1(.:format) |
companies#test1 |
test2_new_company |
GET |
/companies/new/test2(.:format) |
companies#test2 |
companies |
GET |
/companies(.:format) |
companies#index |
|
POST |
/companies(.:format) |
companies#create |
company |
GET |
/companies/:id(.:format) |
companies#show |
param
resources :hoge, only: [:index, :show], param: :user_id
namespace
URI Patternとcontrollerにnamespace Admin::を付ける
namespace :admin do
resources :users, only: [:index, :show]
end
Prefix |
Verb |
URI Pattern |
Controller#Action |
admin_users |
GET |
/admin/users(.:format) |
admin/users#index |
admin_user |
GET |
/admin/users/:id(.:format) |
admin/users#show |
scope
controllerにのみnamespace Adminを付ける
scope module: 'admin' do
resources :authors
end
下記のようにも書ける
resources :authors, module: 'admin'
Prefix |
Verb |
URI Pattern |
Controller#Action |
authors |
GET |
/authors(.:format) |
admin/authors#index |
author |
GET |
/authors/:id(.:format) |
admin/authors#show |
concern
同じような記述をgroup化しておけるイメージ(?)
DRYに書けてすっきりする気がする
concern :categorize do
resources :large_categories, only: [:index, :show] do
get 'test'
end
end
resources :dogs, only: [:index], concerns: :categorize
resources :dogs, only: [:index], concerns: :categorize
Prefix |
Verb |
URI Pattern |
Controller#Action |
dog_large_category_test |
GET |
/dogs/:dog_id/large_categories/:large_category_id/test(.:format) |
large_categories#test |
dog_large_categories |
GET |
/dogs/:dog_id/large_categories(.:format) |
large_categories#index |
dog_large_category |
GET |
/dogs/:dog_id/large_categories/:id(.:format) |
large_categories#show |
dogs |
GET |
/dogs(.:format) |
dogs#index |
cat_large_category_test |
GET |
/cats/:cat_id/large_categories/:large_category_id/test(.:format) |
large_categories#test |
cat_large_categories |
GET |
/cats/:cat_id/large_categories(.:format) |
large_categories#index |
cat_large_category |
GET |
/cats/:cat_id/large_categories/:id(.:format) |
large_categories#show |
cats |
GET |
/cats(.:format) |
cats#index |
constraints
routingに色々な条件を付与できる
デフォルトでは{id: /[^\/]+/}このような指定になっているようです。
:idを正規表現でチェック
下記のように記述すると:idが数字の場合のみ対応するactionが呼ばれる
resources :small_categories, constraints: {id: /\d+/}
下記のような記述方法もある
constraints(id: /\d+/) do
resources :small_categories
end
Prefix |
Verb |
URI Pattern |
Controller#Action |
small_categories |
GET |
/small_categories(.:format) |
small_categories#index |
|
POST |
/small_categories(.:format) |
small_categories#create |
new_small_category |
GET |
/small_categories/new(.:format) |
small_categories#new |
edit_small_category |
GET |
/small_categories/:id/edit(.:format) |
small_categories#edit {:id=>/\d+/} |
small_category |
GET |
/small_categories/:id(.:format) |
small_categories#show {:id=>/\d+/} |
|
PATCH |
/small_categories/:id(.:format) |
small_categories#update {:id=>/\d+/} |
|
PUT |
/small_categories/:id(.:format) |
small_categories#update {:id=>/\d+/} |
|
DELETE |
/small_categories/:id(.:format) |
small_categories#destroy {:id=>/\d+/} |
下記のような場合に便利
resources :small_categories, constraints: {id: /\d+/}, only:[:show]
get '/small_categories/test', to: "small_categories#test"
もしこのようにroutingを書いていた場合に「/small_categories/test」にアクセスすれば「small_categories#test」が呼ばれるが、
constraintsがないと「params[:id]に"test"」が格納されている状態で「small_categories#show」が呼ばれる。
記述する順番を逆にすれば回避出来るが毎回順番を気にしなければいけないのでつらめだと個人的には思う。
また、controller側で:idの値を使用する際もどのようなデータが渡ってくるのかある程度予想出来るので
考えることが減る気がする。
subdomainでチェック
下記のように記述するとアクセスしたsubdomainがadminの場合のみ
該当のmethodが呼ばれるようです。(未確認)
resources :books, only: [:index, :show], constraints: {subdomain: 'admin'}
Prefix |
Verb |
URI Pattern |
Controller#Action |
books |
GET |
/books(.:format) |
books#index {:subdomain=>"admin"} |
book |
GET |
/books/:id(.:format) |
books#show {:subdomain=>"admin"} |
matches?を使用してチェック
constraintsに渡したclassのmatches? methodがtrueを返す場合に
該当のactionが呼ばれる。
例)下記のような処理ではuaがpcの場合に該当のactionが呼ばれる。
class PcConstraint
def matches?(request)
end
end
Rails.application.routes.draw do
get '/', to: 'pc#index', constraints: PcConstraint.new
end
lambdaを使用してチェック
下記のようにlambdaでもチェック可能
get '/', to: 'iphone#index', constraints: lambda {|request| request.user_agent =~ /iPhone/}
Prefix |
Verb |
URI Pattern |
Controller#Action |
|
GET |
/ |
pc#index |
|
GET |
/ |
iphone#index |
defaults
get '/users/:id/default' => 'users#default', defaults: { format: :json}
get '/posts/:id/default' => 'posts#default', defaults: { default_value: :hoge }
Prefix |
Verb |
URI Pattern |
Controller#Action |
|
GET |
/users/:id/default(.:format) |
users#default {:format=>:json} |
|
GET |
/posts/:id/default(.:format) |
posts#default {:default_value=>:hoge} |
redirect
get "user" => redirect("/users")
get "user/:id" => redirect("/users/%{id}")
get 'user/*other' => redirect { |params| "/users/#{params[:other]}"}
Prefix |
Verb |
URI Pattern |
Controller#Action |
users |
GET |
/users(.:format) |
users#index |
user |
GET |
/users/:id(.:format) |
users#show |
|
GET |
/user(.:format) |
redirect(301, /users) |
|
GET |
/user/:id(.:format) |
redirect(301, /users/%{id}) |
|
GET |
/user/*other(.:format) |
redirect(301) |
まとめ
今回使用したサンプルは下記で公開していますので
routing周りをいじって色々試してみてください。
shiro16/blog-samples · GitHub
この記事書いてる間にRailsGuidesのRouting周りの話の日本語版が公開されているので
特に初心者はそっちを見た方がいいとかいう話があるかもしれない・・・