Skip to content

浜松rails3道場 routing編

mackato edited this page May 11, 2011 · 39 revisions

浜松Rails3道場とは、習うより慣れろ方式で、Rails3のツボを浜松のRubyist達へ伝える試みである。

Routing編

参考

前準備

練習用のRailsプロジェクトを作る。参考環境: Ruby 1.9.2, Rails 3.0.7

% rails new routing-dojo
% bundle install

Routingとは

HTTPリクエスト(URL、メソッド)を受け取って、コントローラーのアクションを呼び出す仕組み。また、パスやURLを生成し文字列によるこれらのハードコードを回避することができる。

The Rails router recognizes URLs and dispatches them to a controller’s action. It can also generate paths and URLs, avoiding the need to hardcode strings in your views.(Ruby on Rails Guides)

Routingを使う

確認用のコントローラーを生成

rails g controller catalog view

設定ファイルにrouteを追加する。

# config/routes.rb
match 'products/:id' => 'catalog#view'

Viewで使う

<% # app/views/catalog/view.html.erb %>
<%= link_to 'Product: 2', :controller => 'catalog', :action => 'view', :id => 2 %>

Controllerで使う

# app/controllers/catalog_controller.rb
redirect_to :controller => 'catalog', :action => 'view', :id => 3

Routingを確認する

  • サーバーを起動しブラウザで確認
  • rake routes タスクで確認
  • rails console コマンドで確認
  • テストを書いて確認

コンソールで確認

% rake routes
...
/products/:id(.:format)          {:controller=>"catalog", :action=>"view"}
...
% rails console
Loading development environment (Rails 3.0.7)
> r = ActionController::Routing::Routes
> r.recognize_path '/products/1'
 => {:controller=>"catalog", :action=>"view", :id=>"1"}
> r.generate :controller => 'catalog', :action => 'view', :id => '2' 
 => "/products/2"

Routingのテスト

Railsのコントローラーのテストでは、Routingをテストするための3種類のビルトインアサーションが用意されている。

# test/functional/catalog_controller_test.rb

# assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
assert_generates "/products/1", :controller => 'catalog', :action => 'view', :id => '1'

# assert_recognizes(expected_options, path, extras={}, message=nil)
assert_recognizes({ :controller => "catalog", :action => "view", :id => "2" }, "/products/2")

# assert_routing(path, options, defaults={}, extras={}, message=nil)
assert_routing({ :path => "/products/3", :method => :get },
               { :controller => "catalog", :action => "view", :id => "3" })

url_forなどを使いビューのテストでも検証することができる。

# test/unit/helpers/catalog_helper_test.rb
assert_equal '/products/1', url_for(:controller => 'catalog', :action => 'view', :id => '1')
試してみよう!
  • 'products/:id' の productsと:id の部分を変更してみよう。
  • ビューで :controller や :action などのキーをTypoしてみよう。
参考

Test::Unitの代わりにRSpecを使うと専用のRouting specsが生成される。

# spec/routing/catalog_routing.spec
describe "routing to catalog" do
  it "routes /products/:id to catalog#show for id" do
    { :get => "/products/1" }.should route_to(
      :controller => "catalog",
      :action => "view",
      :id => "1"
    )
  end
end

Named routes

Routeには名前を付けることができる。

# config/routes.rb
match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase

# test/functional/catalog_controller_test.rb
assert_equal "/products/1/purchase", purchase_path(:id => '1')
assert_equal "http://test.host/products/2/purchase", purchase_url(:id => 2)

アプリケーションのrootでは専用のショートカットが使える。

root :to => "welcome#index" # root_path => '/'
試してみよう!
  • 'catalog#view' へのRoutingにも名前を付けてみよう。
  • ビューでxxx_path, xxx_url をTypoしてみよう。

教訓その1

名前なきRoute使うべからず! 名前付きの方がトラブルが少なく、テストもしやすい。

Resource Routing: the Rails標準

Resource Routingを使うことによって、レストフルなURLを通じてリソースフルなコントローラーにアクセスするためのRouteを素早く宣言できる。index, show, new, edit, create, update, deleteといったリソースを操作するためのお決まりのRouteを幾つも書かなくても、たった1行で済ませることができる。

Resource Routingの規約

RailsではResource Routingの規約に基づいて、HTTPメソッドとURLをコントローラーのアクションにマッピングする。

まず、設定ファイルに以下のようなRouteを追加する。

# config/route.rb
resources :products

これにより、PruductsControllerの7つのアクションとHTTPリクエストをマッピングする以下のようなRouteが追加される。

HTTPメソッド リクエストPath アクション 一般的な動作
GET /products index Productのリストを表示する
GET /products/new new 新しいProductを追加するためのフォームを表示する
POST /products create 新しいProductを作成する
GET /products/:id show 指定されたProductを表示する
GET /products/:id/edit edit 指定されたProductを編集するためのフォームを表示する
PUT /products/:id update 指定されたProductを更新する
DELETE /products/:id destroy 指定されたProductを削除する

Paths and URLs

Defining Multiple Resources at the Same Time

Singular Resources

Controller Namespaces and Routing

Nested Resources

Creating Paths and URLs From Objects

Adding More RESTful Actions

Customizing Resourceful Routes

Specifying a Controller to Use

Specifying Constraints

Overriding the Named Helpers

Overriding the new and edit Segments

Prefixing the Named Route Helpers

Restricting the Routes Created

Translated Paths

Overriding the Singular Form

Using :as in Nested Resources

Clone this wiki locally