Top / ruby / rails / RailsGuidesをゆっくり和訳してみたよ / Rails Routing from the Outside In
Last-modified: 2010-09-24 (金) 21:50:19 (10h)

Rails Routing from the Outside In

原文

http://guides.rubyonrails.org/routing.html

裏の裏までルーティング(Rails Routing from the Outside In)

このガイドではユーザー向けのRails のルーティング機能を学ぶことができます。
このガイドを読んだ後、以下のことができるようになります:

  • routes.rb 内のコードの理解
  • お馴染みのリソースフルなスタイルか match メソッドを使った、自身のルーティングの構築
  • 何のパラメーターを、アクションが受け取ることを期待するかの識別
  • ルーティングヘルパを使った、自動的なパスや URL の作成
  • 制約や Rack 終点のような、高度なテクニックの使用

1 ルーターの目的(The Purpose of the Rails Router)

ルーターは URL を認識し、コントローラーのアクションにディスパッチ(送出)します。
それはまた、パスと 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 を生成するでしょう。
これhビューの脆弱性を軽減し、コードを簡単に理解出来るようにするでしょう。

2 リソースルーティング: Rails のデフォルト(Resource Routing: the Rails Default)

リソースルーティングは、与えられたリソースフルなコントローラーのための共通ルーティングの全ての宣言を迅速に、出来るようにします。
index 、 show 、 new 、 edit 、 create 、 update 、 destroy アクションのための分割されたルーティングの宣言の代わりに、
リソースフルなルーティングが、単一行のコード内で宣言します。

2.1 ウェブ上のリソース(Resources on the Web)

ブラウザは、GET 、 POST 、 PUT 、 DELETE のような特定のHTTP メソッドを使って URL からリクエストを作ることにより、 Rails からページをリクエストします。
全てのメソッドは、リソース上の操作を実行するためのリクエストです。
リソースルーティングは、いくつかの関連するリクエストを単一のコントローラー内のアクションにマッピングします。

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 と コントローラーアクションの間のマッピングを提供します。
規約により、全てのアクションはまた、データベース内の 特定の CRUD 操作にマッピングされます。
ルーティングファイル内の、このような単一の登録は、

resources :photos 

アプリケーション内に7つの異なったルーティングを作成します、 Photos コントローラーの全てのマッピングは:

VerbPathaction目的
GET/photosindex全ての photo のリストを表示する
GET/photos/newnew新しい photo を作るための HTML フォームを返す
POST/photoscreate新しい photo の作成する
GET/photos/:idshow特定の photo の表示
GET/photos/:id/editeditphoto の編集のための HTML フォームを返す
PUT/photos/:idupdate特定の photo の更新
DELETE/photos/:iddestroy特定の photo の削除

2.3 パスと URL (Paths and URLs)

リソースフルルーティングの作成は、またアプリケーション内のコントローラーで、いくつかのヘルパを使えるようにするでしょう。
resources :photos の場合:

  • photos_path は /photos を返します。
  • new_photo_path は /photos/new を返します。
  • edit_photo_path は /photos/edit を返します。
  • photo_path(id) は /photos/:id を返します。(例えば、 photo_path(10) は /photos/10 を返します。)

これらのヘルパ全ては、 対応する _url ヘルパ( photos_url のような)を持っていて、
それは現在のホスト、ポート、パスの接頭辞、の接頭辞を、同じパスにつけて返します。

ルーターは、内向きのリクエストにマッチするために HTTP verb や URL を使うので、4つの URL は7つの異なるアクションにマッピングします。

2.4 同時に複数のリソースの定義(Defining Multiple Resources at the Same Time)

一つ以上のリソースのためのルーティングを作成する必要があるなら、単一の resources 呼び出しで全てを定義することによって、タイピングを少し減らすことが出来ます:

resources :photos, :books, :videos

これは、以下と全く同じように動きます。

resources :photos
resources :books
resources :videos

2.5 単一のリソース(Singular Resources)

時々、クライアントがいつも ID を参照すること無しに訪ねるリソースがあります。
一般的な例を挙げると、 /profile は現在ログインしているユーザーのプロフィールをいつも表示します。
この場合、 /profile ( /profile/:id では無く)に show アクションをマップするために単一のリソースを使います。

match "profile" => "users#show"

このリソースルーティングは

resource :geocoder

6つの異なるルーティングをアプリケーション内に作成します、全て Geocoders コントローラーへのマッピングです:

VerbPathaction目的
GET/geocoder/newnew新しい geocoder を作るための HTML フォームの返却
POST/geocodercreate新しい geocoder の作成
GET/geocodershow唯一の geocoder リソースのの表示
GET/geocoder/editeditgeocoder の編集のための HTML フォームの返却
PUT/geocoderupdate唯一の geocoder リソースの更新
DELETE/geocoderdestroygeocoder リソースの削除

単一のルーティング( /account )と複数系のルーティング( /accounts/45 )のために、同じコントローラーを使いたいかもしれないので、単一のリソースは複数のコントローラーにマッピングします。

単一のリソースフルルーティングは、これらのヘルパを生成します:

  • new_geocoder_path は /geocoder/new を返します。
  • edit_geocoder_path は /geocoder/edit を返します。
  • geocoder_path は /geocoder を返します。

複数形のリソースと同様に、 _url で終わる同じヘルパはまたホスト、ポート、パスの接頭辞を含むでしょう。

2.6 コントローラーのネームスペースとルーティング(Controller Namespaces and Routing)

ネームスペース下で、コントローラのグループを整理したいかもしれません。
最も一般的には、 Admin:: ネームスペース下で管理者コントローラーのいくつかをグループ化したいでしょう。
これらのコントローラーを app/controllers/admin ディレクトリ下に配置し、ルーター内でそれらを一緒にグループ化します:

namespace "admin" do
  resources :posts, :comments
end

これは posts コントローラーと、 comments コントローラーの全てに対するいくつかのルーティングを作るでしょう。
Admin::PostsController に対して、 Rails は、以下を作るでしょう:

VerbPathactionヘルパ
GET/admin/photosindexadmin_photos_path
GET/admin/photos/newnewnew_admin_photos_path
POST/admin/photoscreateadmin_photos_path
GET/admin/photos/:idshowadmin_photo_path(id)
GET/admin/photos/:id/editeditedit_admin_photo_path(id)
PUT/admin/photos/:idupdateadmin_photo_path(id)
DELETE/admin/photos/:iddestroyadmin_photo_path(id)

/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 を使用していない場合と同じく残っています。
最後のケースでは、次のパスが PostsController にマッピングされます:

VerbPathactionヘルパ
GET/admin/photosindexphotos_path
GET/admin/photos/newnewnew_photos_path
POST/admin/photoscreatephotos_path
GET/admin/photos/1showphoto_path(id)
GET/admin/photos/1/editeditedit_photo_path(id)
PUT/admin/photos/1updatephoto_path(id)
DELETE/admin/photos/1destroyphoto_path(id)

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 をルーティングするでしょう。
ad URL は magazine を必要とします:

VerbPathactionヘルパ
GET/magazines/1/adsindex特定の magazine のための全ての ad のリストを表示
GET/magazines/1/ads/newnew特定の magazine に属している新しい ad を作るための HTML フォームの返却
POST/magazines/1/adscreate特定の magazine に属している新しい ad の作成
GET/magazines/1/ads/1show特定の magazine に属している特定の ad の表示
GET/magazines/1/ads/1/editedit特定の magazine に属している ad の編集のための HTML フォームを返却
PUT/magazines/1/ads/1update特定の magazine に属している特定の ad の更新
DELETE/magazines/1/ads/1destroy特定の magazine に属している特定の ad の削除

これは magazine_ads_url や edit_magazine_ad_path のようなルーティングヘルパも作成します。
これらのヘルパは、最初のパラメーターとして Magazine のインスタンスを取ります。( magazine_ads_url(@magazine) )

2.7.1 ネストの制限

お望みなら、他のネストしたリソースの中に、リソースをネストできます。
例えば:

resources :publishers do
  resources :magazines do
    resources :photos
  end
end

深くネストされたリソースは、すぐに面倒になります。
このケースでは、例えば、アプリケーションはこのようなパスを認識するでしょう。

/publishers/1/magazines/2/photos/3

これに対応するルーティングヘルパは、 publisher_magazine_photo_url でしょう、それは、3階層にあるオブジェクトの指定を要求します。
確かに、このような状況は、 Jamis Buck の人気記事
良い Rails デザインのルールを提案するのに充分なほど、混乱しやすいです:

リソースは、決して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 のようなヘルパ内で、完全な url_for 呼び出しの代わりに、オブジェクトだけを指定することができます:

<%= 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 アクションにルーティングするでしょう。
それはまた、 preview_photo_url と preview_photo_path を作るでしょう。

メンバルーティングのブロック内で、全てのルーティング名は HTTP verb を指定すると、認識するでしょう。
get 、 put 、 post 、 delete を使えます。
もし、複数のメンバルーティングがないなら、 :on をルーティングに渡し、ブロックを排除できます:

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 アクションにルーティングします。
それはまた search_photos_url と search_photos_path ルーティングヘルパを作成するでしょう。

メンバルーティングと同様に、 :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 リクエストの一部にマッピングする一連のシンボルを指定します。
これらのシンボルの二つは、特別です。 :controller はアプリケーション内のコントローラーの名前にマッピングし、
:action はコントローラー内のアクションの名前にマッピングします。
例えば、デフォルトの Rails のルーティングの1つを考えて下さい:

match ':controller(/:action(/:id))'

/photos/show/1 の内向きのリクエストが、このルーティングによって処理されたら、(ファイル内のそれ以前のルーティングにマッチしなかったことにより)
結果は PhotosController の show アクションを呼び出し、最後のパラメーターを params[:id] として 最後のパラメーター "1" を利用可能にするでしょう。
このルーティングはまた、 /photos の内向きのリクエストを、 PhotosController にルーティングし、
:action と :id はオプションのパラメーターなので、カッコで表されています。

3.2 動的セグメント(Dynamic Segments)

いつものルーティング内に、お望みの数だけ動的セグメントを設定できます。
:controller や :action の他は、 params の一部としてアクションで利用可能でしょう。
もしこのルーティングを設定したなら:

match ':controller/:action/:id/:user_id'

/photos/show/1/2 の内向きのパスは、 PhotosController の show アクションにディスパッチされるでしょう。
params[:id] は "1" で、 params[:user_id] は "2" でしょう。

namespace や :module と、 :controller パスセグメントを使えません。~
もしそうしたければ、 :controller 上で、要求するネームスペースとマッチする制約を使います。例えば:

match ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/

3.3 静的セグメント(Static Segments)

3.4 (The Query String)

3.5 (Defining Defaults)

3.6 (Naming Routes)

3.7 (Segment Constraints)

3.8 (Request-Based Constraints)

3.9 (Advanced Constraints)

3.10 (Route Globbing)

3.11 (Redirection)

3.12 (Routing to Rack Applications)

3.13 (Using root)

4 (Customizing Resourceful Routes)

4.1 (Specifying a Controller to Use)

4.2 (Specifying Constraints)

4.3 (Overriding the Named Helpers)

4.4 (Overriding the new and edit Segments)

4.5 (Prefixing the Named Route Helpers)

4.6 (Restricting the Routes Created)

4.7 (Translated Paths)

4.8 (Overriding the Singular Form)

4.9 (Using :as in Nested Resources)

5 (Inspecting and Testing Routes)

5.1 (Seeing Existing Routes with rake)

5.2 (Testing Routes)

6 (Changelog)

コメント欄(誤訳・誤字があれば教えて頂ければ幸いです。)



Top / ruby / rails / RailsGuidesをゆっくり和訳してみたよ / Rails Routing from the Outside In