Rails 5 Routing Cookbook:

Railsは意見の分かれるフレームワークであり、その基本原則の1つは設定よりも慣習であることを心に留めておく必要があります。 つまり、よほどの理由がない限り、上記のパターンや命名規則を破ってはいけません。

たとえば、index アクションを get 'cars/index' としたり create アクションを post 'car/create' としたりすると、form_for や link_to, redirect_to などのヘルパーメソッドに対する Rails 独自の動作が崩れてしまうでしょう。

意図せずに規約を破った結果は混沌としており、何時間もフレームワークと戦うことになるような、もつれた混乱が生じます。

Photo by Daniele Levis Pelusi on Unsplash

Singular Resource Routes

単一リソースに対するルートも用意することが可能です。 つまり、current_usercurrent_accountに適用されるような、:idを指定せずに検索できるリソースを指します。 5277>

resource :profile 

Nested Routes

時には、リソースを他のリソースの中に入れ子にする必要があります。 たとえば、ガレージにある特定の車の予約を作成したい場合、悪意のあるユーザーによって改ざんされる可能性のあるフォームの隠しフィールドよりも、URL からその車の :id を取得する方が便利な場合があります。 railsでネストされたリソースを作成する方法は次のとおりです:

resources :cars do 
resources :bookings
end

これは、carsにネストされたbookingの7つのCRUDアクションをすべて作成します。 しかし、通常は7つすべてのルートが必要なわけではありません。 また、必要な場合でも、そのすべてがネストされる必要はありません。 私たちが必要とするのは、予約を作成するアクション(ここでは予約を作成するフォームが車のショーアクションにあると仮定します)と既存の予約を編集して更新することだとしましょう。 予約を編集/更新するために車の:idを知る必要がありますか? 答えは明らかにノーです。 したがって、私のアプリケーションでは、次の URL に応答するようにします:

# to CREATE a booking
POST request to http://my-ruby-garage.com/cars/:id/bookings/create# to EDIT a booking
GET request to http://my-ruby-garage.com/bookings/:id/edit# to UPDATE a booking
PATCH request to http://my-ruby-garage.com/bookings/:id/

次のコードで生成されます:

resources :cars do 
resources :bookings, only:
end
resources :bookings, only:

Rails では、シンボルの配列または単一のシンボルをオプション :only またはその逆 :except に供給することにより、標準 CRUD ルートから生成すべきものを修正することができます。 単一のリソースに適用するルート (member routes) や複数のリソースに適用するルート (collection routes) も指定できます。

Member routes

RubyGarage の例で続けると、車はガレージに駐車したりガレージから移動したりすることができます。

resources :cars do 
member do
patch :park
patch :remove
end
end

上記により、http://my-ruby-garage.com/cars/:id/parkhttp://my-ruby-garage.com/cars/:id/remove にパッチリクエストを送り、コントローラ内で特定の車を見つけ、それに応じてリソースを変更することができます。

Collection routes

同じように、時には複数のリソースに対して同時に何らかのアクションを実行したいことがあります。 たとえば、車のコレクションを一度に駐車したり、撤去したりする必要があるかもしれません。 5277>

resources :cars do 
collection do
post :park, as: :bulk_park
post :remove, as: :bulk_remove
end
end

ここで、アプリケーションが http://my-ruby-garage.com/cars/parkhttp://my-ruby-garage.com/cars/remove に応答するように設定し、これらのアクションにそれぞれ bulk_park と bulk_remove という名前を付けています。 名前付きパスを使用して、アプリケーション内の URL パスを生成できることを忘れないでください。 車のコレクションを駐車するためのパス リンクを構築するには、次のように使用できます。

<%= link_to "Park Cars", bulk_park_path, method: :post, class: "button" %>

Namespaced Routes

名前空間ブロック内のリソースの URL パスをプレフィックスし、名前空間と同じ名前のモジュールにある関連コントローラを探そうとします。

namespace :factory do 
resources :cars
end

この例では、次のルートを構築します:

Prefix Verb URI Pattern Controller#Action factory_cars GET /factory/cars(.:format) factory/cars#index
POST /factory/cars(.:format) factory/cars#create factory_car GET /factory/cars/:id(.:format) factory/cars#show
PATCH /factory/cars/:id(.:format) factory/cars#update
PUT /factory/cars/:id(.:format) factory/cars#update
DELETE /factory/cars/:id(.:format) factory/cars#destroy

そして、コントローラも名前空間でなければなりません :

class Factory::CarsController < ApplicationController
# ...
end

Scoped Routes

scopeメソッドは、DRY を維持し関連ルーティング規則をバンドルすることができます。 オプションなしで使用する場合、namespace に似ていますが、関連するコントローラはモジュールで名前空間化する必要はありません。

scope :factory do 
resources :cars
end

次のルートを生成します。 ブラウザに http://my-ruby-garage.com/create-a-car として表示されるパスと、アプリケーション内で create_car としてこのルートを参照できるようにしたいとします。 ウィザードの各ステップを知っているモジュール Wizard::Car があります。

scope module: 'wizards', path: 'create-a-car', as: 'create_car' do
Wizard::Car::STEPS.each do |step|
get step, to: "cars##{step}"
end
post :validate-step, to: 'cars#validate_step'
end

上記のコードは、各ステップで同じパターンを作成します。 たとえば、ステップ1はブラウザからURL http://my-ruby-garage.com/create-a-car/step1でアクセスでき、対応するフォームはhttp://my-ruby-garage.com/create-a-car/validate-stepにポストリクエストを送信し、create_car_step1_pathを呼び出すことでパスを呼び出すことができます。 先ほどの例では、http://my-ruby-garage.com/create-a-carにたどり着いた人を自動的に最初のステップにリダイレクトさせたいかもしれません。

get 'create-a-car', 
to: redirect("/create-a-car/#{Wizard::SpotAccount::STEPS.first}")

Route Defaults

オプションにハッシュを渡すことで、ルートでデフォルトのパラメータを定義できます。

resources :cars do
collection do
get :export, defaults: { format: 'csv' }
end
end

これを使うと、http://my-ruby-garage.com/cars/export にアクセスすると、cars コントローラで export アクションを呼び出し、対応するコントローラアクションはデフォルトで csv で応答します。

Route Globbing

ワイルドカードセグメント (星印を先頭に持つフラグメント) を使用すると、ルートの残りの部分が特定のパラメーターに一致するように指定することができます。 5277>

get '/rent/*slugs', to: 'cars#index', as: :rent_cars

このルートは http://my-ruby-garage.com/rent/lisbon/suv-sedan にマッチし、パラメータを “lisbon/suv-sedan” に設定します。 これは、私たちのデータベースに対するルックアップまたはフィルタリングシステムで使用され、リスボンで suv または sedan のタイプの車を見つけることができます。

Route slugs として検索できる Rails モデルにタグ付けするために、この機能を考慮して Slugcatcher という gem を書いています。

コメントを残す

メールアドレスが公開されることはありません。