Рекурсивные Rails Вложенные Ресурсы - PullRequest
6 голосов
/ 06 октября 2008

У меня есть приложение Rails для управления проектами, где есть модели Project и Task. У проекта может быть много задач, но у задачи может быть много задач, до бесконечности.

Используя вложенные ресурсы, мы можем иметь / проекты / 1 / задачи, / проекты / 1 / задачи / новые, / проекты / 1 / задачи / 3 / редактировать и т.д.

Однако, как вы представляете рекурсивный характер задач RESTful? Я не хочу углубляться в еще один уровень, поэтому, возможно, подойдет следующее:

map.resources :tasks do |t|
    t.resources :tasks
end

Это дало бы мне следующие URL:

/tasks/3/tasks/new   
/tasks/3/tasks/45/edit

Или, возможно, когда дело доходит до отдельной задачи, я могу просто использовать / tasks / 45 / edit

Разумный ли это дизайн?

Cam

Ответы [ 3 ]

6 голосов
/ 06 октября 2008

Выход за пределы одного вложенного маршрута обычно считается плохой идеей.

Со страницы 108 The Rails Way :

" Джемис Буск очень влиятельная фигура в сообществе Rails, почти столько же, сколько сам Дэвид. В феврале 2007 года, в своем блоге, он в основном сказал нам, что глубокое вложение - это то, что нужно Следующее практическое правило: ресурсы никогда не должны быть вложенными более чем на один уровень глубины."

Теперь некоторые могут поспорить с этим (что обсуждается на стр. 109), но когда вы говорите о вложении задач в задачи, это просто не имеет особого смысла.

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

3 голосов
/ 06 октября 2008

нет причин, по которым у них должны быть дочерние URL.

логически:

/projects/1  --> project 1 
/projects/1/edit ( etc )
/tasks/1     --> task 1 
/project/1/tasks --> task list for project 1 
/project/1/tasks/new 
/project/1/tasks/1/edit ->  /tasks/5/edit ( redundancy ) 
/project/1/tasks/1 -> redirect to /tasks/1 
/tasks/1/project -> redirect to /projects/1 
/tasks/3/tasks --> list of tasks that are children tasks of task 3
/tasks/3/tasks/5 -> redirect /tasks/5/    ( because you don't really need to have a recursive URL )
/tasks/5/parents -> list of tasks that are parents of tasks 3
/tasks/5/parents/3 -> redirect /tasks/3/ 

ИМХО нет причин требовать, чтобы URL-адреса были ассоциативными, вам не нужно знать, что задача 5 является дочерней для задачи 3 для редактирования задачи 5.

2 голосов
/ 06 октября 2008

Я в настоящее время нахожусь в проекте, который делает что-то подобное. Я использовал очень элегантный ответ: я добавил столбец parent_id, указывающий на другую задачу. При выполнении вашей модели обязательно выполните следующее:

belongs_to :project
belongs_to :parent, :class_name => "Task"
has_many :children, :class_name => "Task", :foreign_key => "parent_id"

... и тогда вы можете сделать рекурсию по:

def do_something(task)
  task.children.each do |child|
    puts "Something!"
    do_something(child)
  end
end    

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

/project/:project_id/task/:task_id

хотя у него могут быть родители или дети.

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

Смотри также: acts_as_tree

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