ruby/rails/RailsGuidesをゆっくり和訳してみたよ/Rails Routing from the Outside In
原文 †http://guides.rubyonrails.org/routing.html 裏の裏までルーティング(Rails Routing from the Outside In) †このガイドではユーザー向けのRails のルーティング機能を学ぶことができます。
1 ルーターの目的(The Purpose of the Rails Router) †ルーターは URL を認識し、コントローラーのアクションにディスパッチ(送出)します。 1.1 コードに URL を繋ぐ(Connecting URLs to Code) †Rails アプリケーションが、入ってくるリクエストを受け取った時、 GET /patients/17 それがコントローラーのアクションにマッチするか、ルーターに問い合わせます。 match "/patients/:id" => "patients#show" なら、リクエストは、 patients コントローラーの show アクションに、 params 内の { :id => "17" } とともにディスパッチされます。 1.2 コードからパスと URL の生成(Generating Paths and URLs from Code) †パスと URL の生成も出来ます。 @patient = Patient.find(17) <%= link_to "Patient Record", patients_path(@patient.id) %> ルーターは、 /patients/17 を生成するでしょう。 2 リソースルーティング: Rails のデフォルト(Resource Routing: the Rails Default) †リソースルーティングは、与えられたリソースフルなコントローラーのための共通ルーティングの全ての宣言を迅速に、出来るようにします。 2.1 ウェブ上のリソース(Resources on the Web) †ブラウザは、GET 、 POST 、 PUT 、 DELETE のような特定のHTTP メソッドを使って Rails アプリケーションが、入ってくるリクエストを受け取った時、 DELETE /photos/17 それがコントローラーのアクションにマッチするか、ルーターに問い合わせます。 resources :photos
なら、 Rails は、リクエストを、 photos コントローラーの destroy メソッドに、 params 内の { :id => "17" } とともにディスパッチするでしょう。 2.2 CRUD 、Verbs 、 Actions (CRUD, Verbs, and Actions) †Rails では、リソースフルルーティングは HTTP verbs と URL と コントローラーアクションの間のマッピングを提供します。 resources :photos
アプリケーション内に7つの異なったルーティングを作成します、 Photos コントローラーの全てのマッピングは:
2.3 パスと URL (Paths and URLs) †リソースフルルーティングの作成は、またアプリケーション内のコントローラーで、いくつかのヘルパを使えるようにするでしょう。
これらのヘルパ全ては、 対応する _url ヘルパ( photos_url のような)を持っていて、 ルーターは、内向きのリクエストにマッチするために HTTP verb や URL を使うので、4つの URL は7つの異なるアクションにマッピングします。 2.4 同時に複数のリソースの定義(Defining Multiple Resources at the Same Time) †一つ以上のリソースのためのルーティングを作成する必要があるなら、 resources :photos, :books, :videos これは、以下と全く同じように動きます。 resources :photos resources :books resources :videos 2.5 単一のリソース(Singular Resources) †時々、クライアントがいつも ID を参照すること無しに訪ねるリソースがあります。 match "profile" => "users#show" このリソースルーティングは resource :geocoder
6つの異なるルーティングをアプリケーション内に作成します、全て Geocoders コントローラーへのマッピングです:
単一のルーティング( /account )と複数系のルーティング( /accounts/45 )のために、 単一のリソースフルルーティングは、これらのヘルパを生成します:
複数形のリソースと同様に、 _url で終わる同じヘルパはまたホスト、ポート、パスの接頭辞を含むでしょう。 2.6 コントローラーのネームスペースとルーティング(Controller Namespaces and Routing) †ネームスペース下で、コントローラのグループを整理したいかもしれません。 namespace "admin" do resources :posts, :comments end これは posts コントローラーと、 comments コントローラーの全てに対するいくつかのルーティングを作るでしょう。
/photos (頭に /admin 無し)を Admin::PostsController にルーティングしたい場合、以下を使えます。 scope :module => "admin" do resources :posts, :comments end もしくは、単一の場合は、 resources :posts, :module => "admin" /admin/photos を PostsController (頭に Admin:: module 無し)にルーティングしたい場合、以下を使えます。 scope "/admin" do resources :posts, :comments end もしくは、単一の場合は、 resources :posts, :path => "/admin" これらのケース全てで、名前付きルーティングは scope を使用していない場合と同じく残っています。
2.7 ネストしたリソース(Nested Resources) †他のリソースの論理的な子は、リソースを持っているのが一般的です。 class Magazine < ActiveRecord::Base has_many :ads end class Ad < ActiveRecord::Base belongs_to :magazine end ネストしたルーティングは、ルーティング内のこの関連を捉えられます。 resources :magazines do resources :ads end magazines のためのルーティングに加えて、この宣言は AdsController に ads をルーティングするでしょう。
これは magazine_ads_url や edit_magazine_ad_path のようなルーティングヘルパも作成します。 2.7.1 ネストの制限 お望みなら、他のネストしたリソースの中に、リソースをネストできます。 resources :publishers do resources :magazines do resources :photos end end 深くネストされたリソースは、すぐに面倒になります。 /publishers/1/magazines/2/photos/3 これに対応するルーティングヘルパは、 publisher_magazine_photo_url でしょう、それは、3階層にあるオブジェクトの指定を要求します。 リソースは、決して1階層以上ネストしないべきでしょう。 2.8 オブジェクトからのパスと URL の作成(Creating Paths and URLs From Objects) †ルーティングヘルパの使用に加えて、 Rails はまたパラメーターの配列から、パスと URL を作成できます。 resources :magazines do resources :ads end magazine_ad_path を使う時、数値の ID の代わりに、 Magazine と Ad のインスタンスを渡せます。 <%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %> また、オブジェクトのセットと url_for を使え、 Rails は自動的にあなたが必要なルーティングを決定するでしょう: <%= link_to "Ad details", url_for(@magazine, @ad) %> この場合では、 Rails は @magazine は Magazine で、 @ad は Ad だと思い、従って、 magazine_ad_path helper を使うでしょう。 <%= link_to "Ad details", [@magazine, @ad] %> ただ magazine へだけリンクしたい場合、 Array も省くことが出来ます: <%= link_to "Magazine details", @magazine %> これは、 URL としてモデルのインスタンスを扱うことが出来、リソースフルなスタイルを使う主な利点です。 2.9 もっと RESTful なアクションの追加(Adding More RESTful Actions) †デフォルトで作られる RESTful なルーティング7つに制限されません。 2.9.1 メンバルーティングの追加 メンバルーティングを追加するために、リソースブロック内にメンバーブロックを追加してください: resources :photos do member do get 'preview' end end これは /photos/1/preview と GET だと認識し、 PhotosController の preview アクションにルーティングするでしょう。 メンバルーティングのブロック内で、全てのルーティング名は HTTP verb を指定すると、認識するでしょう。 resources :photos do get 'preview', :on => :member end 2.9.2 コレクションルーティングの追加 コレクションにルーティングを追加するために: resources :photos do collection do get 'search' end end これは Rails が、 /photos/search と GET のようなパスを理解出来るようにし、 PhotosController の search アクションにルーティングします。 メンバルーティングと同様に、 :on をルーティングに渡せます: resources :photos do get 'search', :on => :collection end 2.9.3 注意書き もしリソースフルルーティングに多くの余分なアクションを追加していると気づいたなら、 3 リソースフルでないルーティング(Non-Resourceful Routes) †リソースルーティングに加えて、 Rails は、任意の URL をアクションにルーティングするのための強力なサポートを持っています。 通常、リソースフルなルーティングを使うべきですが、シンプルなルーティングがより適切な多くの場合があります。 特に、シンプルなルーティングは、古い URL を新しい Rails のアクションにマッピングするのを簡単にします。 3.1 バインドされたパラメーター(Bound Parameters) †いつものルーティングを設定する場合、 Rails が内向きの HTTP リクエストの一部にマッピングする一連のシンボルを指定します。 match ':controller(/:action(/:id))'
/photos/show/1 の内向きのリクエストが、このルーティングによって処理されたら、 3.2 動的セグメント(Dynamic Segments) †いつものルーティング内に、お望みの数だけ動的セグメントを設定できます。 match ':controller/:action/:id/:user_id'
/photos/show/1/2 の内向きのパスは、 PhotosController の show アクションにディスパッチされるでしょう。 namespace や :module と、 :controller パスセグメントを使えません。~ match ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/ 3.3 静的セグメント(Static Segments) †ルーティングを作成する時に、静的セグメントを指定できます: match ':controller/:action/:id/with_user/:user_id'
このルーティングは、 /photos/show/1/with_user/2 のようなパスに対応するでしょう。 3.4 クエリ文字列(The Query String) †params はクエリ文字列から任意のパラメーターを含むでしょう。 match ':controller/:action/:id'
/photos/show/1?user_id=2 の内向きのパスは、 PhotosController の show アクションにディスパッチされるでしょう。 3.5 デフォルトの定義(Defining Defaults) †ルーティングの内側で、 :controller と :action シンボルを明示的に使う必要はありません。 match 'photos/:id' => 'photos#show' このルーティングで、 Rails は、 /photos/12 の内向きのパスを PhotosController の show アクションにマッチするでしょう。 :defaults オプションのためのハッシュを供給することによって、ルーティング内の他のデフォルトを定義することも出来ます。 match 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' } Rails は photos/12 の内向きのパスを PhotosController の show アクションにマッチし、 3.6 名前付きルーティング(Naming Routes) †:as オプションを使って、ルーティングのための名前を指定します。 match 'exit' => 'sessions#destroy', :as => :logout これは名前付きヘルパとして logout_path と logout_url をアプリケーション内に作成するでしょう。 3.7 セグメントの制約(Segment Constraints) †動的セグメントのためのフォーマットを適用するために :constraints オプションを使うことが出来ます。 match 'photos/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ } このルーティングは /photos/A12345 のようなパスにマッチするでしょう。 match 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/ :constraints は正規表現を受け取ります。 match '/:id' => 'posts#show', :constraints => {:id => /^\d/} しかしながら、全てのルーティングは先頭に固定されているので、アンカーを使う必要はありません。 例えば、次のルーティングは、 to_param の値が 1-hello-world のような常に数字で始まる posts と match '/:id' => 'posts#show', :constraints => { :id => /\d.+/ } match '/:username' => 'users#show' 3.8 リクエストベースの制約(Request-Based Constraints) †String を返す Request 上の任意のメソッドに基づいて、ルーティングを制限することが出来ます。 セグメントの制約を指定するのと同じ方法で、リクエストベースの制約を指定します。 match "photos", :constraints => {:subdomain => "admin"} ブロック形式の中で、制約を指定することも出来ます。 namespace "admin" do constraints :subdomain => "admin" do resources :photos end end 3.9 高度な制約(Advanced Constraints) †もっと高度な制約がある場合、 Rails が使うべき matches? に対応するオブジェクトを渡せます。 class BlacklistConstraint def initialize @ips = Blacklist.retrieve_ips end def matches?(request) @ips.include?(request.remote_ip) end end TwitterClone::Application.routes.draw do match "*path" => "blacklist#index", :constraints => BlacklistConstraint.new end 3.10 glob ルーティング(Route Globbing) †glob ルーティングは、特定のパラメーターがルーティングの残りの全ての部分にマッチすべきだと指定する方法です。 match 'photos/*other' => 'photos#unknown' このルーティングは photos/12 か /photos/long/path/to/12 にマッチし、 ワイルドカードセグメントは、あるルーティングの最後にある必要はありません。 match 'books/*section/:title' => 'books#show' これは books/some/section/last-words-a-memoir にマッチし、 技術的に、確かにルーティングは一つ以上のワイルドカードセグメントを持つことができ、 match '*a/foo/*b' => 'test#index' は、 zoo/woo/foo/bar/baz にマッチし、 3.11 リダイレクト(Redirection) †ルーティング内の redirect ヘルパを使って、任意のパスを他のパスにリダイレクトできます: match "/stories" => redirect("/posts") また、パス内でマッチした動的セグメントを、リダイレクト先のパス内で再利用できます。 match "/stories/:name" => redirect("/posts/%{name}") redirect にブロックを与えることもできます、それは params と(オプションで) request オブジェクトを受け取ります: match "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" } match "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" } これらの全ての場合、リダイレクト先ホスト(http://www.example.com)を指定しないなら、 3.12 Rack アプリケーションへのルーティング(Routing to Rack Applications) †"posts#index" のような PostsController 内の index アクションに対応する String の代わりに、 match "/application.js" => Sprockets Sprockets が call に応答し、 [status, headers, body] を返す限り、 好奇心のため、"posts#index" は実際、 PostsController.action(:index) に展開され、それは有効な Rack アプリケーションを返します。 3.13 root の使用(Using root) †Rails が "/" に何をルーティングするか、 root メソッドで指定できます: root :to => 'pages#main' root ルーティングをファイルの最後に置くべきです。 4 リソースルルーティングのカスタマイズ(Customizing Resourceful Routes) †resources :posts によって、生成されたデフォルトのルーティングとヘルパは通常役に立ちますが、 4.1 利用するコントローラーの指定(Specifying a Controller to Use) †:controller オプションは、リソースのために使うコントローラーを明示的に指定することが出来ます。 resources :photos, :controller => "images" これは /photo から始まる内向きのパスを認識します、が、 Images コントローラーにルーティングするでしょう:
このリソースのパスを生成するために、 photos_path や new_photos_path 等を使って下さい。 4.2 制約の指定(Specifying Constraints) †暗黙な id 上の 必要なフォーマットを指定するのに、 :constraints を使えます。 resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/} この宣言は、指定された正規表現にマッチするように :id パラメーターを制約します。 ブロック形式を利用して、ルーティングの数字に適用するための単一の制約を指定できます: constraints(:id => /[A-Z][A-Z][0-9]+/) do resources :photos resources :accounts end もちろん、このコンテキスト内でリソースフルでないルーティング内で利用可能なもっと高度な制約を使えます。 4.3 名前付きヘルパのオーバーライド(Overriding the Named Helpers) †:as オプションは、名前付きルーティングヘルパのための通常の命名を上書きできます。 resources :photos, :as => "images" は、 /photos で始まる内向きのパスを認識し、リクエストを PhotosController にルーティングするでしょう:
4.4 new と edit セグメントをオーバーライド(Overriding the new and edit Segments) †:path_names オプションは、パス内に自動的に生成された "new" と "edit" セグメントをオーバーライドできます。 resources :photos, :path_names => { :new => 'make', :edit => 'change' } これは以下のようなパスをルーティングに認識させます。 /photos/make /photos/1/change 実際のアクション名はこのオプションによって変更されません。 全てのルーティングのためのこのオプションを均一に変更したいなら、スコープを使えます: scope :path_names => { :new => "make" } do # rest of your routes end 4.5 名前付きルーティングヘルパの接頭辞(Prefixing the Named Route Helpers) †Rails がルーティングのために生成する名前付きルーティングヘルパの接頭辞を指定するのに :as オプションを使えます。 scope "admin" do resources :photos, :as => "admin_photos" end resources :photos これは、 admin_photos_path や new_admin_photo_path のようなルーティングヘルパを提供するでしょう。 ルーティングのグループの接頭辞を付けるには、 :as を scope と共に使います。 scope "admin", :as => "admin" do resources :photos, :accounts end resources :photos, :accounts ネームスペーススコープは、 :module と :path 接頭辞だけでなく、自動的に :as を追加するでしょう。 4.6 作成されたルーティングの制限(Restricting the Routes Created) †デフォルトでは Rails は、アプリケーション内の全ての RESTful ルーティングのためのデフォルトのアクションの7つ全て resources :photos, :only => [:index, :show] 今では /photos への GET リクエストは成功するでしょう :except オプションは、 Rails は作成すべきではないルーティングかルーティングのリストを指定します: resources :photos, :except => :destroy この場合、 Rails は destroy のためのルーティング( /photos/:id への DELETE リクエスト)を除いた全ての通常のルーティングを作成するでしょう。 アプリケーションが多くの RESTful なルーティングを持っている場合、 4.7 翻訳されたパス(Translated Paths) †scope を使って、リソースによって生成されたパスの名前を変更できます: scope(:path_names => { :new => "neu", :edit => "bearbeiten" }) do resources :categories, :path => "kategorien" end Rails は CategoriesController へのルーティングを作成します。
4.8 単一形式のオーバーライド(Overriding the Singular Form) †リソースの単一形式を定義したいなら、 Inflector に追加ルールを追加すべきでしょう。 ActiveSupport::Inflector.inflections do |inflect| inflect.irregular 'tooth', 'teeth' end 4.9 ネストしたリソース内での :as の使用(Using :as in Nested Resources) †:as オプションは、ネストしたルーティングヘルパ内でリソースのために自動的に生成された名前をオーバーライドします。 resources :magazines do resources :ads, :as => 'periodical_ads' end これは、 magazine_periodical_ads_url や edit_magazine_periodical_ad_path のようなルーティングヘルパを作るでしょう。 5 ルーティングの検査とテスト(Inspecting and Testing Routes) †Rails はルーティングの検査とテストのための仕組みを提案します。 5.1 rake と共に既存のルーティングを見る(Seeing Existing Routes with rake) †アプリケーション内で利用可能なルーティングの全ての完全なリストが欲しいなら、 rake routes コマンドを実行してください。
例えば、ここに RESTful なルーティングのための rake routes の出力の一部があります: users GET /users {:controller=>"users", :action=>"index"}
formatted_users GET /users.:format {:controller=>"users", :action=>"index"}
POST /users {:controller=>"users", :action=>"create"}
POST /users.:format {:controller=>"users", :action=>"create"}
CONTROLLER 環境変数を設定することにより、特定のコントローラーをマッピングするルーティングに、リストを制限するかもしれません。 $ CONTROLLER=users rake routes rake routes からの出力は、行が折り返さないまで端末のウィンドウを広げれば、もっと読みやすくなることがわかるでしょう。 5.2 ルーティングのテスト(Testing Routes) †ルーティングは(アプリケーションの他の部分のように)テスト戦略に含まれるべきです。
5.2.1 assert_generates アサーション 特定のパスを生成するオプションの特定のセットをアサートするために、 assert_generates を使って下さい。 assert_generates "/photos/1", { :controller => "photos", :action => "show", :id => "1" } assert_generates "/about", :controller => "pages", :action => "about" 5.2.2 assert_recognizes アサーション assert_recognizes アサーションは、 assert_generates の逆です。 assert_recognizes({ :controller => "photos", :action => "show", :id => "1" }, "/photos/1") HTTP verb を指定するために :method 引数を渡せます。 assert_recognizes({ :controller => "photos", :action => "create" }, { :path => "photos", :method => :post }) RESTful なルーティングの解釈をテストするのにも、リソースフルなヘルパを使えるでしょう。 assert_recognizes new_photo_url, { :path => "photos", :method => :post } 5.2.3 assert_routing アサーション assert_routing アサーションは、ルーティングを両方の方法でチェックします: assert_routing({ :path => "photos", :method => :post }, { :controller => "photos", :action => "create" }) 6 Changelog(Changelog) †
コメント欄(誤訳・誤字があれば教えて頂ければ幸いです。) † |