ネストされたルートのかなり一般的なケースがあります、これは次のようなものです(ある種の疑似表記):
'/:username/photos' => Show photos for User.find_by_username
'/photos' => Show photos for User.all
一言で言えば:ユーザーがいます。彼らは写真を持っています。彼らの写真を彼らのページに表示したいです。また、ユーザーに関係なく、すべての写真を表示できるようにしたいと考えています。ルートをRESTfulに保ち、組み込みのresource
メソッドを使用することは、正しい方法のように感じます。
オプション1これを行うには、PhotosController#indexに条件を使用して、指定されたパラメーターを確認し、写真のリストを取得してビューを設定します(すべての写真よりもユーザーの写真では異なります)。ルーティングも簡単です。
resources :photos, :only => [:index]
scope ':/username' do
resources :photos
end
ブーム。 Railsはこのように設定されていましたが、ルートの後は、状況はさらに複雑になります。それはseemのようです。 PhotosController#indexアクションの条件付きのバックは、ますます肥大化し、ひどく多くの分析を行っています。アプリケーションが成長し、写真を表示する方法の数が増えるにつれて、状況は悪化するだけです。
オプション2は、ユーザーの写真を処理するためのUser :: PhotosControllerと、すべての写真の表示を処理するためのPhotosControllerを持つことです。
resources :photos, :only => [:index]
namespace :user, :path => '/:username' do
resources :photos
end
これにより、次のルートが生成されます。
photos GET /photos(.:format) {:action=>"index", :controller=>"photos"}
user_photos GET /:username/photos(.:format) {:action=>"index", :controller=>"user/photos"}
POST /:username/photos(.:format) {:action=>"create", :controller=>"user/photos"}
new_user_photo GET /:username/photos/new(.:format) {:action=>"new", :controller=>"user/photos"}
edit_user_photo GET /:username/photos/:id/edit(.:format) {:action=>"edit", :controller=>"user/photos"}
user_photo GET /:username/photos/:id(.:format) {:action=>"show", :controller=>"user/photos"}
PUT /:username/photos/:id(.:format) {:action=>"update", :controller=>"user/photos"}
DELETE /:username/photos/:id(.:format) {:action=>"destroy", :controller=>"user/photos"}
これはかなりうまくいくと思いますが、すべてがUserモジュールの下にあり、他のものと統合すると問題が発生する可能性があるように感じます。
pdate:Railsのロジックをオーバーライドするのではなく機能させるのをよりクリーンに感じるので、オプション2の実装を進めました。これまでのところ順調ですが、名前空間の名前を:users
に変更し、:as => :user
を追加して、User
モデルと競合しないようにする必要もあります。ユーザー名を返すために、User
モデルのto_param
メソッドもオーバーライドしました。パスヘルパーもこのように機能します。
この方法についてのフィードバックをお待ちしています。私は物事を期待どおりにやっていますか、それともこの機能を誤用していますか?
これを行う最適な方法はアプリケーションによって異なりますが、私の場合は確かにオプションBです。名前空間付きルートを使用すると、モジュールを使用してさまざまな懸念事項をさまざまなコントローラーに非常にクリーンな方法で分離できます。また、名前空間固有のコントローラーを使用して、特定の名前空間のすべてのコントローラーに共有機能を追加しています(たとえば、before_filterを追加して、名前空間のすべてのリソースの認証と権限を確認しています)。
この場合、浅いネストされたルートの使用を検討しましたか?
浅いルートの入れ子入れ子になったリソースは、扱いにくいURLを生成することがあります。これに対する解決策は、浅いルートのネストを使用することです。
resources :products, :shallow => true do
resources :reviews
end
これにより、次のルートを認識できるようになります。
/products/1 => product_path(1)
/products/1/reviews => product_reviews_index_path(1)
/reviews/2 => reviews_path(2)
私は自分のアプリの1つでこれと同様のことをしました。あなたは正しい軌道に乗っています。私が行ったのは、ネストされたリソースを宣言し、Rails 3.でActive Recordの柔軟なarelベースの構文を使用してクエリを作成することです。
# config/routes.rb
resources :photos, :only => :index
resources :users do
resources :photos
end
# app/controllers/photos_controller.rb
def index
@photos = Photo.scoped
@photos = @photos.by_user(params[:user_id]) if params[:user_id]
# ...
end
Example::Application.routes.draw do
resources :accounts, :path => '' do
resources :projects, :path => '', :except => [:index]
end
end
例を以下に示します: http://jasoncodes.com/posts/Rails-3-nested-resource-slugs
私の現在のプロジェクトでそれを適用しました。
次のように、1人のユーザーの写真を取得するための別のルートを定義できます。
get '(:username)/photos', :to => 'photos#index'
しかし、ジミーが上記で投稿したネストされたリソースを使用することをお勧めします。これが最も柔軟なソリューションだからです。