Rails RESTful удаляет во вложенных ресурсах - PullRequest
3 голосов
/ 07 ноября 2010

Хорошо, вот пример сценария. Существует студенческий ресурс resources :students, и студенты имеют и принадлежат ко многим коллекциям: resources :clubs, resources :majors и т. Д.

Так что мы можем достаточно легко настроить наши маршруты ...

resources :clubs do
  resources :students
end
resources :majors do
  resources :students
end
resources :students do
  resources :clubs
  resources :majors
end

, который генерирует нам набор стандартных маршрутов RESTful

  • / клубы
  • / клубы /: ID
  • / клубы /: club_id / студентов
  • / клубы /: club_id / студенты /: id
  • / майоров
  • / майоров /: ID
  • / специализаций /: major_id / студентов
  • / майоров /: major_id / студентов /: ID
  • / студенты
  • / студентов /: ID
  • / студентов /: student_id / клубы
  • / студентов /: student_id / клубы /: ID
  • / студентов /: student_id / майоров
  • / студентов /: student_id / майоров /: ID

Так вот мой вопрос. С семантикой REST, как можно удалить мажор для студента? Просмотр учеников по специальности /majors/:major_id/students/:id покажет, что этот студент находится в «коллекции» конкретного специалиста. Но путь для удаления: id указывает на StudentsController#destroy, что полностью удалит студента. Упс! Так что, может быть, мы пойдем другим путем и выполним DELETE на ресурсе /students/:student_id/majors/:id, и теперь UnderwaterBasketweaving больше не предлагается в этой школе ... Ой!

Теперь предоставлено, что мы можем установить метод уничтожения ClubsController, MajorsController или StudentsController для поиска club_id, major_id или student_id, но, скажем, в дальнейшем мы хотим добавить Fraternities, GraduatingClasses и т. Д. Каждый класс будет начать состоять из огромных условных переключателей, чтобы посмотреть, какой параметр присутствует ... и затем найти коллекцию верхнего ресурса и удалить нижний ресурс, или наоборот. Сами модели должны решить, удаляют ли они себя, если у них больше нет ассоциативных записей ... "Уничтожить" на этом ресурсе стало по-настоящему неверным ...

Есть ли более простой способ сделать это? Даже популярные плагины релакс-рельсов, такие как make_resourceful или resource_controller, сдувают плетение UnderwaterBasket при удалении его из Joj's Majors или полностью удаляют JohnDoe при удалении его из основного UnderwaterBasketweaving. Казалось бы, есть возможность взглянуть на ассоциацию, чтобы понять желаемый эффект семантики и то, что должен делать «уничтожить».

Опять же, я смотрю на все это неправильно? Разве это не UnderwaterBasketweaving -> Joe, а UnderwaterBasketweaving + Joe как единый ресурс, и то, что мы удаляем, действительно не Joe или UnderwaterBasketweaving, но ресурс, представляющий комбинацию? Тем не менее, это непросто, когда контроллерами являются студенты и майоры, которые фактически представляют ресурсы с одним и тем же именем (MVC действительно стал RV ... в подходе "соглашения" и не разрабатывает контроллеры, которые могут не иметь никакого отношения к название модели или путь к ней) То есть вы удаляете майора или студента; выбери свой яд ...

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

... major.student.delete ... Есть ли способ, чтобы объект ActiveRecord «студента» узнал, что ему было отправлено сообщение «delete» в цепочке методов, начинающейся с объекта AR «major»?

1 Ответ

2 голосов
/ 07 ноября 2010

Что ж, стандартный подход RESTful заключается в использовании has_many :through и создании ролика для ресурса ассоциации. Именование ресурсов ассоциации всегда сложно, но я попытаюсь для этого примера.

resources :majors do
  resources :studies
  resources :students
end
resources :students do
  resources :studies
  resources :majors
end

Модели будут, конечно:

class Major < ActiverRecord::Base
  has_many :studies
  has_many :students, :through => :studies
end

и т.д.. (прокомментируйте, если хотите, чтобы я уточнил)

Тогда для студента вы бы НЕ УДАЛИТЬ, это связано @student.major, но его @student.studies.where :major => @major.

...