Railsのルーティングを理解する

rails
この記事は約15分で読めます。

railsのルーティング周りについて、自分自身がルーティング設定をする時に迷わないようにするため、また内部でどのような処理がされているのかをイメージしながら設定を書けるようになるため、調べた内容をまとめてみる。

最初は、ネストしたルーティングの設定の仕方がよくわからなかったが、スコープを意識することで定義したいリソースを生成したい場合にどのようにルーティングを設定すればよいのかが段々とわかるようになってきた。

  • rails-4.2.5で動作確認した内容です。
  • 間違いがあれば、コメント等でお知らせいただけますと幸いです。
  • サンプルコードは、特に実用性を深く考慮したものではないです。

ルーターの役割

ルーターは,PATH_INFOの情報をもとに、HTTPリクエストを適切なコントローラーのアクションへディスパッチする(正確には、通常Dispatcherオブジェクトがdispatchする)。例えば,以下のような設定を考えてみる。

上記設定で生成されるルーティングは以下のようになり,

GET /books/1のようなHTTPリクエストを送ると、books_controllerのshowメソッドにディスパッチされる。

ルーティング設定

getやpostなどのHTTPメソッド宣言やmatchのような宣言でURLパターンを記述したり、resourcesやresourceのリソーススコープとcollectionやmemberなどのスコープレベルを組み合わせたりすることでルーティングを設定していく。

resources

リソースフルな一連のルーティングを生成する。デフォルトで以下のアクションが用意されている。@api_onlyは,rails5からAPI機能に特化した開発を行なうために追加されたオプションであり,apiモードの時に生成されるアクションでは:new:editが含まれない形になっている。

resourcesを使って以下のような設定をすると、上記のデフォルトアクションに対応するルーティングが生成される。

この設定により以下のルーティングが生成される。

param

セグメント:idは、paramオプションで変えることもできる。,

上記設定により以下のようなルーティングが生成される。

only、except

onlyやexceptオプションを使うと、ルーティングを特定のアクションに限定したり、ルーティングから特定のアクションを除外したりすることができる。以下はonlyオプションを使って:showアクションのみに限定した場合の例。

以下のルーティングが生成される。

collection、 member、new

resourcesは、newおよび後述するcollectionとmemberを使っても同じように設定を記述することができる。実際、resourcesは呼び出しの中でこれらのスコープを使っている。以下のような設定を書いてみたところ、resources :booksと同様のルーティングが生成されるのを確認できる(実際にはこのような書き方はしないだろう。。)。

nested

nestedスコープは、resourcesスコープで:#{singular}_#{param}の動的パスセグメントを生成する。例えば、以下ではパス/reviewsに対して、:book_idという動的パスセグメントを生成している。

以下のルーティングが生成される。

:book_idでなく:idを使いたい場合は、memberスコープにすればよい。

resource

単数形リソース(id参照を必要としないリソース)を使用する時に使う。デフォルトで以下のアクションが用意されている。

例えば、ログインしているユーザーに対するリソースフルな一連のルーティングを生成したい場合、以下のように設定できる。

上記設定により生成されるルーティングは以下のようになる。

indexアクションのルーティングが含まれない点が、resourcesと異なる。

スコープで生成されるリソース

ActionDispatch::RoutingモジュールのMapper::Resources::Resource(resourcesで呼ばれる)やMapper::Resources::SingletonResourceクラス(resourceで呼ばれる)を見ると、各スコープでどのようなパスセグメントが生成されるのか把握することができる。

ActionDispatch::Routing::Mapper::Resources
from www.omniref.com

以下表にまとめてみる。

Scope Level Resources, Resource Resource (SingularResource)
collection path path
member “#{path}/:#{param}” path (default scope)
new “#{path}/new” “#{path}/new”
nested “#{path}/:#{singular}_#{param}” (default scope) path
Called Inside collection
・get :index
・post :create
new
・get :new
member
・get :edit
・get :show
・patch :update
・put :update
・delete :destroy
collection
・post :create
new
・get :new
member
・get :edit
・get :show
・patch :update
・put :update
・delete :destroy

例えば以下の設定例では、下表のようになる。

Scope Level Resources, Resource Resource (SingularResource)
collection /books /user
member /books/:id /user
/user/profile
new /books/new /user/new
nested /books/:book_id/reviews

scope-routing

collection

id参照のないリソースを使用したい時に使う。resourcesまたはresourceのスコープ外で宣言するとArgumentErrorになる。

以下のルーティングが生成される。

member

id参照のあるリソースを使用したい時に使う。resourcesまたはresourceのスコープ外で使うとArgumentErrorになる。

以下のルーティングが生成される。

ちなみに、memberを使わないと以下のルーティングとなる。

pathヘルパーメソッドのprefixおよび動的パスセグメント名が異なっているので注意。

root

アプリケーションルートのルーティングを生成する。以下の3つの定義は同じとなるが、1)の書き方が最もシンプル。

namespaceやscope内でも宣言することができる。例えば、以下はscopeのブロック内で、3)の設定をしたことと同じである。

以下のルーティングが生成される。

HttpHelpers

HttpHelpersモジュールには、代表的なHTTPメソッドのヘルパーメソッドが定義されている。これらのメソッドを使ってresourcesで生成されるルーティングの設定を記述すると以下のようになる。

match

HttpHelpersモジュールのメソッドは内部でこのメソッドを呼んでいる。getやpostでは、呼び出しに対応するHTTPメソッドが1つに決定されるが、matchではviaオプションを使って複数のHTTPメソッドに対応するルーティングを生成することができる。

以下のルーティングが生成される。

anchor

anchorオプションをfals`に設定すると、pathで始まるリソースに一致するリクエスト全てで有効となる。

scope

様々なスコープを作り、ルーティング設定を記述することができる。ここでのオプションは、matchやresourcesでも同様に使うことができる。例えば、以下はpath: '/books'オプションを保持したスコープを作り、そのスコープ内でさらにgetメソッドを使ってルーティングを設定している。

以下のルーティングが生成される。

path

as

スコープ内でasオプションで指定される値をpathヘルパーメソッドのprefixに追加する。

以下では、pathオプションを保持するスコープでasオプションを使ってpathヘルパーメソッドのprefixをそれぞれbooksとbookに設定している。

以下のルーティングが生成される。

controller

スコープ内でcontrollerオプションで指定されるcontrollerを使う。

以下では、path、controller、asの3つのオプションを保持したスコープを作り、その中でいくつかのルーティングを設定している。

以下のルーティングが生成される。

action

スコープ内でactionオプションで指定されるactionを使う。

以下では、path、controller、action、asの4つのオプションを保持したスコープを作り、ルーティングを設定している。

以下のルーティングが生成される。

module

スコープ内でmoduleオプションで指定されるmoduleを使う。

以下では、path、module、asの3つのオプションを保持したスコープを作り、adminモジュールのadminコントローラーのindexアクションに対するルーティングを設定している。

以下のルーティングが生成される。

shallow_path

スコープ内でshallow_pathオプションで指定される値を、shallowオプションが指定されているリソースのメンバーリソース(id参照のある)の先頭に追加する。

以下では、reviewsの一連のid参照をするリソースにunpublishedというパスセグメントを追加している。

shallow_prefix

スコープ内でshallow_prefixオプションで指定される値を、shallowオプションが指定されているリソースのメンバーリソース(id参照のある)に対応するpathヘルパーメソッドのprefixに追加する。

以下の例では、unpublishedをpathヘルパーメソッドのprefixに追加している。

以下のルーティングが生成される。

path_names

path_namesオプションで指定される値で、newやeditなどの自動生成されるパスセグメントをオーバーライドする。

以下のルーティングが生成される。

shallow

浅いネストを設定する。

以下のルーティングが生成される。

constraints

通常Dispatcherがルーティングエンドポイントとなっているところに、一層処理を挟む形となる。

これを利用すると、動的パスセグメントのURL形式に特定の制約を課すことができる。constraintsオプションのHashキーには、Requestクラスのメソッド名を指定することもでき、その場合、valueはメソッドの返り値の型と一致させる必要がある。

idパラメータが数値のみを許可する例。

以下のルーティングが生成される。

ローカルからのリクエストの時のみ許可する例。

Requestクラスのlocal?メソッドを使う。

ActionDispatch::Journey::Route
from www.omniref.com

constraintsに任意のオブジェクトを指定する

matches?メソッドに応答するオブジェクトを指定することができる。

Procやlambdaなどのcallに応答するオブジェクトを指定することもできる。

以下のルーティングが生成される。

defaults

パラメータのデフォルト値を設定する。

以下のルーティングが生成される。

namespace

scopeで以下のように書いたのと同じになる。

concern

ルーティング設定を再利用することができる。resourcesやresourceのオプションで指定できる。

以下のルーティングが生成される。

Rackアプリケーションの指定

toオプションにrackアプリケーションを指定することができる。

以下のようなルーティングが生成される。

コントローラーのアクションもrackのエンドポイント

toには、アクションを直接指定することもできる。

redirect

toオプションにredirectを使うと、動的セグメントを利用してリダイレクトさせることができる。

以下のルーティングが生成される。

mount

アプリケーションにRackアプリケーションやEngineをマウントすることができる。内部では、matchが呼び出されている。

Ex3の例では、以下のルーティングが生成され、/myappでアプリケーションにアクセスすることができる。

ルーティング適用の順番

ルーティングは、先に設定しているものが優先される。

参考リンク

  • http://railsguides.jp/routing.html
  • http://railsguides.jp/engines.html
Ruby on Rails 4 アプリケーションプログラミング
山田 祥寛
技術評論社
売り上げランキング: 23,409

コメント

タイトルとURLをコピーしました