Как Rails: если у проекта есть задачи, его не следует удалять: как я могу это исправить? - PullRequest
5 голосов
/ 17 ноября 2011

Привет, у меня есть проект, и у каждого проекта есть задачи. Задача принадлежит проекту. Прежде чем удалить проект, я хочу проверить, есть ли связанные задачи. Если есть задачи, я не хочу удалять проект. Если связанных задач нет, проект следует удалить. Можете ли вы помочь мне с кодом? Чего мне не хватает?

class Project < ActiveRecord::Base  
  before_destroy :check_tasks    

  def check_tasks 
    if Project.find(params[:id]).tasks  
      flash[:notice] = 'This project has tasks.'
      redirect_to :action => 'list_projects'    
    end 
  end
end

Ответы [ 3 ]

6 голосов
/ 17 ноября 2011

Возврат false из метода before_destroy для предотвращения уничтожения экземпляра.

Метод также должен возвращать значимую ошибку для устранения неполадок.

class Project < ActiveRecord::Base
  before_destroy :check_tasks

  def check_tasks
    if self.tasks.any?
      errors.add_to_base "Project has tasks and cannot be destroyed."
      return false
    end
  end
end

Примечание: flash [: note] и params [: attr_name] могут использоваться только с контроллеров.

2 голосов
/ 17 ноября 2011

У вас есть пара проблем здесь.

  1. У вас нет (или не должно быть) доступа к переменной params (она доступна только в контроллерах и представлениях, если вы не 'Вы передаете его в модель, что, вероятно, не то, что вам нужно).
  2. Ваши if проверяют project.tasks, который является массивом - даже пустой массив оценивается как true, так что ваш другой кодветвление никогда не произойдет независимо от того, есть ли у проекта задачи или нет.
  3. Вероятно, вы должны устанавливать сообщения об ошибках для представления из действия ProjectsController # destroy, а не в вашей модели.

Решения:

  1. Изменить Project.find(params[:id]) до self - вы хотите проверять задачи для каждого экземпляра проекта.
  2. Измените проверку в своем операторе if с if self.tasks на if self.tasks.any?, которая возвращает желаемое значение (false, если массив пуст, true в противном случае).
  3. Переместите flash [: note] из вашей модели в контроллер, а также вызов redirect_to, к которому они принадлежат.Это означает, что ваш метод check_tasks можно изменить следующим образом:

код:

def check_tasks
  return !self.tasks.any?
end
1 голос
/ 17 ноября 2011

Должен ли чек быть self вместо этого?(не уверен, откуда вы получаете параметры [: id]).

Пока еще не проверил это - но так как мне нужно что-то подобное для моей модели Users, я посмотрю, как это получится, и получуназад к вам.

class Project < ActiveRecord::Base  
 before_destroy :check_tasks

 private

 def check_tasks
   #edited 
   if tasks.empty?  
     false
   end 
 end
...