Подтвердить что ты не робот

Маршрутизация вложенных ресурсов в Rails 3

У меня довольно распространенный случай для вложенных маршрутов, я чувствую, что выглядит примерно так (в какой-то псевдонетации):

'/:username/photos' => Show photos for User.find_by_username
'/photos' => Show photos for User.all

В двух словах: У меня есть пользователи. У них есть фотографии. Я хочу показать свои фотографии на своей странице. Я также хочу, чтобы показывать все фотографии, независимо от пользователя. Я бы хотел, чтобы мои маршруты RESTful и использование встроенных методов resource чувствовали себя как правильный способ сделать это.


Вариант 1 для этого состоит в том, чтобы индекс PhotosController # использовал условие, чтобы проверить, какие параметры указаны, и получить список фотографий и установить представление (другое для фотографий пользователя, чем для всех фотографий). Это даже легко проложить маршрут:

resources :photos, :only => [:index]
scope ':/username' do
  resources :photos
end

Boom. Казалось бы, для этого была настроена Rails. Однако после маршрутов все усложняется. Это условное выражение в действии indexController # index просто становится все более раздутым и делает очень много дегазации. По мере того, как приложение растет, а также количество способов, которыми я хочу показывать фотографии, это будет только ухудшаться.

Вариант 2 может состоять в том, чтобы пользовательский:: 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, и я чувствую, что это может вызвать проблемы, когда я его интегрирую с другими вещами.

Вопросы

  • Есть ли у кого-нибудь опыт в этом?
  • Может ли кто-нибудь поделиться лучшим способом справиться с этим?
  • Любые дополнительные плюсы и минусы, которые следует учитывать при любом из этих вариантов?

Обновление. Я уже реализовал вариант 2, потому что он чувствует себя более чистым, чем логика Rails, а не ее переопределение. Пока все идет хорошо, но мне также нужно было переименовать мое пространство имен в :users и добавить :as => :user, чтобы он не столкнулся с моей моделью User. Я также переопределил метод to_param модели User, чтобы вернуть имя пользователя. Помощники по пути все еще работают так же.

Я по-прежнему ценю отзывы об этом методе. Я делаю то, что ожидал, или я злоупотребляю этой функциональностью?

4b9b3361

Ответ 1

Лучший способ сделать это зависит от приложения, но в моем случае это, конечно, вариант B. Использование маршрутов с расширением имен я могу использовать модуль, чтобы разделить различные проблемы с отдельными контроллерами очень просто. Я также использую контроллер, специфичный для пространства имен, для добавления общих функций ко всем контроллерам в определенном пространстве имен (добавление, например, before_filter для проверки подлинности и разрешения для всех ресурсов в пространстве имен).

Ответ 2

Рассматривали ли вы использование мелкого вложенного маршрута в этом случае?

Неверное расположение маршрута Время от времени вложенные ресурсы могут создавать громоздкие 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)

Ответ 3

Я сделал что-то похожее на это в одном из моих приложений. Ты на правильном пути. То, что я сделал, было объявить вложенные ресурсы и построить запрос, используя гибкий синтаксис ActiveL в Active Directory в Rails 3. В вашем случае это может выглядеть примерно так:

# 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

Ответ 4

Вы можете определить отдельный маршрут для получения фотографий для одного пользователя:

get '(:username)/photos', :to => 'photos#index'

Но я бы посоветовал просто использовать вложенный ресурс, который Jimmy опубликовал выше, поскольку это наиболее гибкое решение.

Ответ 5

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

Просто применил это в моем текущем проекте.