1

I'm trying to set up a simple soft delete system by adding a before_destroy callback which sets the deleted flag and then returns false (to prevent real destroy from happening).

class Project < ActiveRecord::Base

    belongs_to :user

    before_destroy :soft_delete

    def soft_delete
        self.update( is_deleted: 1 )
        false
    end

end

This does not result in the record getting updated. I'm not sure why. I see [1m[36m (0.4ms)[0m [1mROLLBACK[0m in my logs, but I'm not sure it's relevant or not.

4

4 回答 4

3

我想self.update_columns(is_deleted: true)可能会工作...

于 2013-09-11T20:16:21.423 回答
2

尝试 self.update_attributes(is_deleted: 1)

在Rails 4.2.4上为我工作

于 2017-11-27T14:20:21.347 回答
1

这里

如果 before_* 回调返回 false,则所有后面的回调和相关操作都将被取消。如果 after_* 回调返回 false,则后面的所有回调都将被取消。回调通常按照定义的顺序运行,但定义为模型上的方法的回调除外,这些方法最后调用。

于 2013-09-11T20:02:27.493 回答
0

我建议直接在控制器中覆盖destroy方法。与往常一样,尝试遵循 Rails 的“胖模型瘦控制器”最佳实践。我会在模型中创建大部分逻辑,然后简单地从控制器中调用它,如下所示:

在您的模型中:

def soft_delete!
    update_attribute(:is_deleted, 1)
    #remove any other attributes you want here (ie. if there are tasks associated with projects and such they should also be cascade "soft deleted here"
end 

在您的控制器中:

def destroy
   @project = Project.find(params[:id])
   @project.soft_delete!
   redirect_to projects_path
end

类似的东西会起作用 - 最重要的是,您可能想要:

  • 使 soft_delete 返回布尔值,以便您可以在控制器中打开它并重定向到其他地方
  • 软删除其他模型中的其他相关属性(我在其中添加了评论)
于 2013-09-11T20:21:09.427 回答