РЕСТАЛЬНО Вложенные Маршруты Ресурса с Единственными Идентификаторами - PullRequest
8 голосов
/ 23 мая 2010

В моем Rails-приложении у меня довольно стандартные отношения has_many между двумя сущностями. A Foo имеет ноль или более Bars; Bar принадлежит ровно одному Foo. И Foo, и Bar идентифицируются одним целочисленным значением ID. Эти значения уникальны для всех соответствующих экземпляров.

Бар зависит от существования Foo: нет смысла иметь Бар без Foo.

Есть два способа RESTful ссылки на экземпляры этих классов. Если Foo.id равен 100 и Bar.id равен 200:

  1. Ссылка на каждый Foo и Bar через их собственные маршруты "верхнего уровня" URL, например:

    • / Foo / 100
    • / бар / 200
  2. Панель ссылок как вложенный ресурс через его экземпляр Foo:

    • / Foo / 100
    • / Foo / 100 / бар / 200

Мне нравятся вложенные маршруты в # 2, так как они более точно представляют фактические отношения зависимости между объектами. Тем не менее, это, кажется, требует много дополнительной работы за очень небольшой выигрыш. Предполагая, что я знаю о конкретном баре, мне не нужно говорить о конкретном Foo; Я могу извлечь это из самого бара. Фактически, я, вероятно, должен проверять маршрутизируемый Foo везде, куда бы я ни пошел (чтобы вы не могли сделать / foo / 150 / bar / 200, предполагая, что Bar 200 не назначен для Foo 150). В конечном счете, я не вижу, что это приносит мне.

Итак, есть ли другие аргументы за или против этих двух схем маршрутизации?

Точка выяснения

Меня больше всего интересуют обновления / шоу / удаления RESTful для определенных баров. Для получения списка Bars для определенного Foo (который обычно является действием index в Rails) имеет смысл иметь вложенный маршрут, такой как / foo / 100 / bar. Страница на этом маршруте может так же легко ссылаться на / bar / x, как и / foo / 100 / bar / x.

Ответы [ 4 ]

6 голосов
/ 23 мая 2010

Вы ищете мелкие маршруты. Как вы указали, идея наличия глубоко вложенного маршрута для таких вещей, как «создание, обновление», не нужна, поскольку вы нацеливаетесь на нужную запись напрямую.

На самом деле я никогда не занимался мелкой маршрутизацией, поэтому я передам эпизод с Railscast, где Райан Бейтс объясняет это, вероятно, лучше, чем я: 139 Вложенных ресурсов .

Редактировать: Вы можете прочитать немного больше о руководствах по маршрутизации 3.8.4 .

4 голосов
/ 23 мая 2010

Как вы уже знаете, каждый предмет должен иметь уникальный адрес. Я бы предположил, что чем короче и проще адрес, тем лучше для всех участников - вашего кода маршрутизации, ваших клиентских приложений и т. Д. Если вы можете идентифицировать Bar по уникальному идентификатору, я, вероятно, указал бы только это в URL.

Вам не нужно терять семантическую информацию о назначении Баром Foo. Это может быть частью представления.

В качестве усовершенствования вы можете разрешить клиенту обращаться к Bar 200 как / foo / 100 / bar / 200, но затем перенаправлять на предпочтительный адрес / bar / 200 /, используя, например, 303 («See Other»). ) ответ.

2 голосов
/ 23 мая 2010

Rails поверхностное вложение дает нам лучшее из обоих миров: оно позволяет нам использовать специфичные для Foo маршруты, в которых есть смысл (создание, новый, индексирование), и маршруты только для Bar в противном случае (показать, изменить , обновить, уничтожить).

К сожалению, новый DSL маршрутизации в Rails 3 (который я использую) поддерживает , а не пока поддерживает мелкую маршрутизацию (в бета-версии 3). Похоже, в работах , но на сегодняшний день он не работает.

Однако вы можете подделать его, сопоставив ресурс дважды, один раз вложенный и один раз поверхностный:

resources :foo do
  resources :bar, :only => [:index, :new, :create]    
end
resources :bar, :only => [:show, :edit, :update, :destroy]

Это будет приливать меня до тех пор, пока опция: shallow не будет запущена и снова запущена.

0 голосов
/ 23 мая 2010

Лично, если каждый бар зависит от Foo, вариант № 2 имеет больше смысла. Например, если Foo - это блог, а Bar - это сообщение, то гораздо более логично получить доступ к конкретному сообщению с example.bloghosting.com/blog/1/post/2, чем example.bloghosting.com/post/21.

Сделайте это с последней версией Rails:

class Food < ActiveRecord::Base
    has_many :bars
end

class Bar < ActiveRecord::Base
    belongs_to :foo
end

Затем в роутере Rails (/config/routes.rb):

map.resources :foos do |foo|
    foo.resource :bars
end

Для получения дополнительной информации см. Маршрутизация Rails извне * и Документация по Rails API .

...