Ruby on Rails
ルーティング
サーチ…
前書き
備考
「ルーティング」は、一般に、アプリケーションによってURLがどのように「処理」されるかを示します。 Railsの場合は、一般的にどのコントローラーか、そのコントローラーのどのアクションが特定の着信URLを処理するかです。 Railsアプリケーションでは、ルートは通常config/routes.rb
ファイルに置かれます。
リソースルーティング(基本)
ルートはconfig/routes.rb
定義されています。それらは、 resources
またはresource
メソッドを使用して、しばしば関連ルートのグループとして定義されます。
resources :users
は次の7つのルートを作成します。すべてはUsersController
アクションにマッピングされていUsersController
:
get '/users', to: 'users#index'
post '/users', to: 'users#create'
get '/users/new', to: 'users#new'
get '/users/:id/edit', to: 'users#edit'
get '/users/:id', to: 'users#show'
patch/put '/users/:id', to: 'users#update'
delete '/users/:id', to: 'users#destroy'
アクション名は、上記のto
パラメータの#
後に表示さto
ます。これらの名前のメソッドは、次のようにapp/controllers/users_controller.rb
で定義する必要があります。
class UsersController < ApplicationController
def index
end
def create
end
# continue with all the other methods…
end
あなたが生成されますアクションを制限することができますonly
かexcept
。
resources :users, only: [:show]
resources :users, except: [:show, :index]
任意の時点で、次のコマンドを実行することによって、アプリケーションのすべてのルートを表示できます。
$ rake routes
$ rake routes
# OR
$ rails routes
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
特定のコントローラにマップするルートだけを表示するには:
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
# OR
$ rails routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
-g
オプションを使用してルートを検索できます。これは、ヘルパーメソッド名、URLパス、またはHTTP動詞と部分的に一致するルートを示します。
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
# OR
$ rails routes -g new_user # Matches helper method
$ rails routes -g POST # Matches HTTP Verb POST
さらに、開発モードでrails
サーバを実行しているときは、 <hostname>/rails/info/routes
上から順に優先順位が一致する検索フィルタを使用して、すべてのルートを表示するWebページにアクセスできます。それは次のようになります:
ヘルパー | HTTP動詞 | パス | コントローラ#アクション |
---|---|---|---|
パス/ URL | [パスマッチ] | ||
users_path | 取得する | /users(.:format) | users#index |
役職 | /users(.:format) | users#create | |
new_user_path | 取得する | /users/new(.:format) | users#new |
edit_user_path | 取得する | /users/:id/edit(.:format) | users#edit |
user_path | 取得する | /users/:id(.:format) | ユーザー#show |
パッチ | /users/:id(.:format) | users#update | |
プット | /users/:id(.:format) | users#update | |
削除 | /users/:id(.:format) | ユーザーは#破壊する |
ルートは、メソッドの使用メンバーのみ(ないコレクション)のために利用可能と宣言することができresource
の代わりに、 resources
してroutes.rb
。 resource
場合、 index
ルートはデフォルトでは作成されませんが、明示的に次のようなものを要求する場合に限ります。
resource :orders, only: [:index, :create, :show]
制約
制約を使用して使用可能な経路をフィルタリングできます。
制約を使用するには、次のようないくつかの方法があります。
たとえば、特定のIPアドレスのみがルートにアクセスすることを許可する要求されたベース制約:
constraints(ip: /127\.0\.0\.1$/) do
get 'route', to: "controller#action"
end
他の同様の例を参照してください。ActionDispatch :: Routing :: Mapper :: Scoping 。
より複雑な処理をしたい場合は、より高度な制約を使用して、ロジックをラップするクラスを作成することができます。
# lib/api_version_constraint.rb
class ApiVersionConstraint
def initialize(version:, default:)
@version = version
@default = default
end
def version_header
"application/vnd.my-app.v#{@version}"
end
def matches?(request)
@default || request.headers["Accept"].include?(version_header)
end
end
# config/routes.rb
require "api_version_constraint"
Rails.application.routes.draw do
namespace :v1, constraints: ApiVersionConstraint.new(version: 1, default: true) do
resources :users # Will route to app/controllers/v1/users_controller.rb
end
namespace :v2, constraints: ApiVersionConstraint.new(version: 2) do
resources :users # Will route to app/controllers/v2/users_controller.rb
end
end
1つのフォーム、複数の送信ボタン
また、フォームのsubmitタグの値を制約として使用して、別のアクションにルーティングすることもできます。複数の送信ボタンがあるフォーム(「プレビュー」や「送信」など)がある場合は、javascriptを使用してフォームのroutes.rb
先URLを変更する代わりに、この制約をroutes.rb
に直接取り込むことができます。とたとえばcommit_param_routing宝石あなたはレールを利用することができsubmit_tag
Rails submit_tag
最初のパラメータでは、フォームコミットパラメータの値を変更できます
# app/views/orders/mass_order.html.erb
<%= form_for(@orders, url: mass_create_order_path do |f| %>
<!-- Big form here -->
<%= submit_tag "Preview" %>
<%= submit_tag "Submit" %>
# => <input name="commit" type="submit" value="Preview" />
# => <input name="commit" type="submit" value="Submit" />
...
<% end %>
# config/routes.rb
resources :orders do
# Both routes below describe the same POST URL, but route to different actions
post 'mass_order', on: :collection, as: 'mass_order',
constraints: CommitParamRouting.new('Submit'), action: 'mass_create' # when the user presses "submit"
post 'mass_order', on: :collection,
constraints: CommitParamRouting.new('Preview'), action: 'mass_create_preview' # when the user presses "preview"
# Note the `as:` is defined only once, since the path helper is mass_create_order_path for the form url
# CommitParamRouting is just a class like ApiVersionContraint
end
スコープのルート
Railsはルートを整理するいくつかの方法を提供します。
URLによるスコープ :
scope 'admin' do
get 'dashboard', to: 'administration#dashboard'
resources 'employees'
end
これにより、次のルートが生成されます
get '/admin/dashboard', to: 'administration#dashboard'
post '/admin/employees', to: 'employees#create'
get '/admin/employees/new', to: 'employees#new'
get '/admin/employees/:id/edit', to: 'employees#edit'
get '/admin/employees/:id', to: 'employees#show'
patch/put '/admin/employees/:id', to: 'employees#update'
delete '/admin/employees/:id', to: 'employees#destroy'
サーバー側では、別のサブフォルダにいくつかのビューを保存し、管理者ビューとユーザービューを分離する方が理にかなっています。
スコープ(モジュール別)
scope module: :admin do
get 'dashboard', to: 'administration#dashboard'
end
module
は、指定された名前のサブフォルダの下にあるコントローラファイルを探します。
get '/dashboard', to: 'admin/administration#dashboard'
パスヘルパーのプレフィックスの名前を変更するには、 as
パラメータを追加as
ます
scope 'admin', as: :administration do
get 'dashboard'
end
# => administration_dashboard_path
Railsは、 namespace
メソッドを使用して、上記のすべてを行う便利な方法を提供しnamespace
。次の宣言は同等です
namespace :admin do
end
scope 'admin', module: :admin, as: :admin
コントローラーによるスコープ
scope controller: :management do
get 'dashboard'
get 'performance'
end
これによりこれらのルートが生成されます
get '/dashboard', to: 'management#dashboard'
get '/performance', to: 'management#performance'
浅いネスティング
リソースルートは、可能な限りURLを短縮するのに役立つ:shallow
オプションを受け入れます。リソースは1つ以上のレベルの深さでネストされるべきではありません。これを回避する1つの方法は、浅いルートを作成することです。目的は、必要のない親コレクションのURLセグメントから離れることです。最終的に生成されるネストされたルートは、 :index
、 :create
、および:new
アクションのみです。残りは、独自の浅いURLのコンテキストで保持されます。スコープをカスタマイズするための2つのオプションがあります。
:shallow_path :指定されたパラメータでメンバーパスを接頭辞付ける
scope shallow_path: "sekret" do resources :articles do resources :comments, shallow: true end end
:shallow_prefix :指定されたパラメータを名前付きヘルパーに追加する
scope shallow_prefix: "sekret" do resources :articles do resources :comments, shallow: true end end
私たちはまた、 shallow
ルートをもっと詳しく説明することができます:
resources :auctions, shallow: true do
resources :bids do
resources :comments
end
end
代わりに以下のようにコード化されています。
resources :auctions do
shallow do
resources :bids do
resources :comments
end
end
end
結果ルートは次のとおりです。
接頭辞 | 動詞 | URIパターン |
---|---|---|
bid_comments | 取得する | /bids/:bid_id/comments(.:format) |
役職 | /bids/:bid_id/comments(.:format) | |
new_bid_comment | 取得する | /bids/:bid_id/comments/new(.:format) |
edit_comment | 取得する | /comments/:id/edit(.:format) |
コメント | 取得する | /comments/:id(.:format) |
パッチ | /comments/:id(.:format) | |
プット | /comments/:id(.:format) | |
削除 | /comments/:id(.:format) | |
auction_bids | 取得する | /auctions/:auction_id/bids(.:format) |
役職 | /auctions/:auction_id/bids(.:format) | |
new_auction_bid | 取得する | /auctions/ :auction_id/bids/new(.:format) |
edit_bid | 取得する | /bids/:id/edit(.:format) |
入札 | 取得する | /bids/:id(.:format) |
パッチ | /bids/:id(.:format) | |
プット | /bids/:id(.:format) | |
削除 | /bids/:id(.:format) | |
オークション | 取得する | /auctions(.:format) |
役職 | /auctions(.:format) | |
new_auction | 取得する | /auctions/new(.:format) |
edit_auction | 取得する | /auctions/:id / edit(.:format) |
オークション | 取得する | /auctions/:id(.:format) |
パッチ | /auctions/:id(.:format) | |
プット | /auctions/:id(.:format) | |
削除 | /auctions/:id(.:format) |
注意深く生成されたルートを分析すると、URLのネストされた部分は、表示するデータを判断するために必要なときにのみ含まれています。
懸念事項
ネストされたルートでの繰り返しを避けるため、懸案事項は再利用可能な共通リソースを共有する素晴らしい方法を提供します。懸念を作成するには、メソッドの使用concern
内routes.rb
ファイル。このメソッドは、シンボルとブロックを想定しています。
concern :commentable do
resources :comments
end
ルート自体を作成していない間、このコードではリソース上の:concerns
属性を使用できます。最も簡単な例は次のとおりです。
resource :page, concerns: :commentable
同等のネストされたリソースは次のようになります。
resource :page do
resource :comments
end
これは、例えば、以下の経路を構築する。
/pages/#{page_id}/comments
/pages/#{page_id}/comments/#{comment_id}
意味のあることを心配するには、懸念を利用する複数のリソースが必要です。追加のリソースは、以下のいずれかの構文を使用して問題を呼び出すことができます。
resource :post, concerns: %i(commentable)
resource :blog do
concerns :commentable
end
リダイレクション
次のように、Railsルートでリダイレクトを実行できます。
get '/stories', to: redirect('/posts')
match "/abc" => redirect("http://example.com/abc")
すべての未知のルートを指定されたパスにリダイレクトすることもできます:
match '*path' => redirect('/'), via: :get
# or
get '*path' => redirect('/')
match '*path' => redirect('/')
メンバールートとコレクションルート
リソース内のメンバーブロックを定義すると、そのリソースベースのルートの個々のメンバーに作用するルートが作成されます。
resources :posts do
member do
get 'preview'
end
end
これにより、次のメンバールートが生成されます。
get '/posts/:id/preview', to: 'posts#preview'
# preview_post_path
収集ルートを使用すると、リソースオブジェクトのコレクションに作用するルートを作成できます。
resources :posts do
collection do
get 'search'
end
end
これにより、次の収集ルートが生成されます。
get '/posts/search', to: 'posts#search'
# search_posts_path
別の構文:
resources :posts do
get 'preview', on: :member
get 'search', on: :collection
end
期間を持つURLパラメータ
ID番号よりも複雑なurlパラメータをサポートしたい場合は、値にピリオドが含まれていると、パーサーに問題が発生する可能性があります。ピリオドに続くものは、フォーマット(つまり、json、xml)とみなされます。
この制限を回避するには、制約を使用して受け入れ可能な入力を拡大します。
たとえば、urlの電子メールアドレスでユーザーレコードを参照する場合は、次のようにします。
resources :users, constraints: { id: /.*/ }
ルートルート
root
メソッドを使用して、ホームページのルートをアプリに追加することができます。
# config/routes.rb
Rails.application.routes.draw do
root "application#index"
# equivalent to:
# get "/", "application#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def index
render "homepage"
end
end
ターミナルでは、 rake routes
(Rails 5のrails routes
)が生成されます:
root GET / application#index
ホームページは通常、最も重要なルートであり、ルートは表示される順番で優先順位付けされるため、 root
ルートは通常、ルートファイルの最初のルートにする必要があります。
追加のRESTfulアクション
resources :photos do member do get 'preview' end collection do get 'dashboard' end end
これにより、 デフォルトの7つのRESTfulルートに加えて 、次のルートが作成されます 。
get '/photos/:id/preview', to: 'photos#preview'
get '/photos/dashboards', to: 'photos#dashboard'
単一行でこれを行うには、次のようにします。
resources :photos do get 'preview', on: :member get 'dashboard', on: :collection end
/new
パスにアクションを追加することもできます:
resources :photos do get 'preview', on: :new end
どちらが作成されます:
get '/photos/new/preview', to: 'photos#preview'
あなたのRESTfulルートにアクションを追加するときは注意してください。恐らく別のリソースがありません!
有効なロケールの範囲
アプリケーションが異なる言語で使用できる場合は、通常、URLに現在のロケールが表示されます。
scope '/(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
root 'example#root'
# other routes
end
ルートは、 I18n.available_locales
定義されたロケールを介してアクセスできます。
別のアプリケーションをマウントする
mountは、現在のアプリケーション内で使用される別のアプリケーション(基本的にラックアプリケーション)またはレールエンジンをマウントするために使用されます
構文:
mount SomeRackApp, at: "some_route"
これで、route helper some_rack_app_path
またはsome_rack_app_url
を使用して、上記のマウントされたアプリケーションにアクセスできます。
しかし、このヘルパー名の名前を変更したい場合、次のようにすることができます:
mount SomeRackApp, at: "some_route", as: :myapp
これはmyapp_path
とmyapp_url
ヘルパーを生成し、このマウントされたappにナビゲートできます。
リダイレクトとワイルドカードルート
あなたのユーザーに便利なURLを提供したいが、既に使用している別のURLに直接マップしたい場合。リダイレクトを使用する:
# config/routes.rb
TestApp::Application.routes.draw do
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
end
まあ、それは面白い速かった。ここでの基本的な原則は、 #redirect
メソッドを使用して別のルートに1つのルートを送信することです。あなたのルートが非常にシンプルな場合、それは本当に簡単な方法です。しかし、元のパラメータも送信したい場合は、 %{here}
内のパラメータを取得して少し体操をする必要があります。すべてを囲む単一引用符に注意してください。
上記の例では、:asパラメータでエイリアスを使用することで、便宜のためにルートの名前を変更しました。これにより、#_pathヘルパーのようなメソッドでその名前を使用できます。再度、 $ rake routes
を質問でテストします。
ルートを複数のファイルに分割する
あなたのルートファイルが圧倒的に大きければ、あなたのルートを複数のファイルに置き、Rubyのrequire_relative
メソッドで各ファイルをインクルードすることができます:
config/routes.rb
: YourAppName::Application.routes.draw do
require_relative 'routes/admin_routes'
require_relative 'routes/sidekiq_routes'
require_relative 'routes/api_routes'
require_relative 'routes/your_app_routes'
end
config/routes/api_routes.rb
: YourAppName::Application.routes.draw do
namespace :api do
# ...
end
end
ネストされたルート
ネストされたルートを追加する場合は、 routes.rb
ファイルに次のコードをroutes.rb
できます。
resources :admins do
resources :employees
end
これにより、次のルートが生成されます。
admin_employees GET /admins/:admin_id/employees(.:format) employees#index
POST /admins/:admin_id/employees(.:format) employees#create
new_admin_employee GET /admins/:admin_id/employees/new(.:format) employees#new
edit_admin_employee GET /admins/:admin_id/employees/:id/edit(.:format) employees#edit
admin_employee GET /admins/:admin_id/employees/:id(.:format) employees#show
PATCH /admins/:admin_id/employees/:id(.:format) employees#update
PUT /admins/:admin_id/employees/:id(.:format) employees#update
DELETE /admins/:admin_id/employees/:id(.:format) employees#destroy
admins GET /admins(.:format) admins#index
POST /admins(.:format) admins#create
new_admin GET /admins/new(.:format) admins#new
edit_admin GET /admins/:id/edit(.:format) admins#edit
admin GET /admins/:id(.:format) admins#show
PATCH /admins/:id(.:format) admins#update
PUT /admins/:id(.:format) admins#update
DELETE /admins/:id(.:format) admins#destroy