Маршрутизация вложенных ресурсов в Rails 3 - PullRequest
33 голосов
/ 17 февраля 2011

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

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

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


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

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

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

Опция 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"}

Это работает довольно хорошо, я думаю, но все находится под пользователеммодуль, и я чувствую, что это может привести к проблемам при интеграции его с другими вещами.

Вопросы

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

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

Я все равно буду благодарен за отзыв об этом методе.Я делаю вещи ожидаемым образом или неправильно использую эту функцию?

Ответы [ 5 ]

7 голосов
/ 22 февраля 2011

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

Глубокое Вложение Маршрута Иногда вложенные ресурсы могут создавать громоздкие 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)
6 голосов
/ 05 марта 2011

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

1 голос
/ 17 февраля 2011

Я сделал нечто похожее на это в одном из моих приложений. Вы на правильном пути. Я объявил вложенные ресурсы и создал запрос, используя гибкий синтаксис на основе arel Active Record в 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
0 голосов
/ 16 ноября 2011
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

Только что применил это в моем текущем проекте.

0 голосов
/ 17 февраля 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...