如何Rails:如果项目有任务,则不应删除它:我该如何解决这个问题?

时间:2011-11-17 16:38:36

标签: ruby-on-rails orphaned-objects

嗨,我有一个项目,每个项目都有任务。任务属于项目。在删除项目之前,我想检查是否有相关任务。如果有任务我不想删除项目。如果没有关联任务,则应删除该项目。你能帮我解释一下代码吗?我错过了什么?

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 个答案:

答案 0 :(得分:6)

从before_destroy方法返回 false 以防止实例被销毁。

该方法还应该返回有意义的错误以进行故障排除。

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 [:notice]和params [:attr_name]只能在控制器中使用。

答案 1 :(得分:2)

你有几个问题。

  1. 您没有(或不应该)访问params变量(仅在控制器和视图中可用,除非您将其传递给模型,这可能不是您想要的)
  2. 您的if检查project.tasks是一个数组 - 即使是一个空数组也会计算为true,因此无论项目是否有任务,您的其他代码分支都不会发生。
  3. 您可能应该从ProjectsController#destroy action为视图设置错误消息,而不是在您的模型中。
  4. 解决方案:

    1. Project.find(params[:id])更改为self - 您想要检查项目的每个实例的任务。
    2. if语句中的格式从if self.tasks更改为if self.tasks.any?,这会返回您想要的值(如果数组为空则为false,否则为true )。
    3. 将闪光灯[:notice]从您的模型移动到控制器,以及redirect_to调用,它们属于您的控制器。这意味着您的check_tasks方法可以更改为以下内容:
    4. 代码:

      def check_tasks
        return !self.tasks.any?
      end
      

答案 2 :(得分:1)

支票应该是自我吗? (不确定从哪里得到params [:id]。)

但是还没有检查过 - 但是因为我需要类似于我的用户模型的东西,我会看到它是如何工作的并回复给你。

class Project < ActiveRecord::Base  
 before_destroy :check_tasks

 private

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