如何在Rails中实现类似Gmail的“撤销”功能?

16

当删除记录时,我认为拥有类似于 Gmail 的"撤销"方法比显示一个烦人的弹窗框("你确定吗?")更加重要。

我的实现方式是在模型中添加一个“deleted_at”时间戳列,并在调用destroy方法时进行时间戳标记。

def destroy
  @foo = Foo.find(params[:id])
  @foo.update_attribute(:deleted_at, Time.now)
  ...
end

撤销/恢复,我只需要将同一列设置为 nil 即可

def revert
  @foo = Foo.find(params[:id])
  @foo.update_attribute(:deleted_at, nil)
  ...
end
我将只需要添加一个条件来过滤掉"已删除"的foo在调用find方法时。或许可以设置cron或后台任务,在一段时间后真正销毁这些"已删除"的foo。 这对我来说可行且易于实现,但我很想知道是否有更好的实现方式?也许有一个插件或gem可以提供这个功能,而我不知道?

你真的在意它什么时候被删除吗?一个标志不够吗? - Brad Wilson
4
是的,我现在并不在意它被删除的时间,但那个知识可能会在未来有用。无论如何,我认为时间戳是一个很好的标志。 - JasonOng
1
我同意一般的观点。然而,预先满足这样的需求可能会让其他开发人员误以为该(时间戳)信息当前正在使用的位置。当它实际上没有被使用时,它代表着一个松散的线索,对于未经培训的人来说通常是令人沮丧和耗时的。 - Magne
5个回答

4

确实有一些插件可以在Agile Web Development找到。

以下是这些插件的链接和摘要,它们似乎符合您的描述:

  1. Acts as Paranoid:将您的Active Records设为"paranoid"(偏执模式)。删除记录不会删除行,而是设置一个deleted_at字段。Find方法被重载以跳过已删除的记录。
  2. Acts as soft deletable:提供了对ActiveRecord模型进行软删除的功能。

似乎Acts As Paranoid在未来的ActiveRecord版本中可能会出现一些问题,因为它覆盖了find方法。Acts As Soft Deletable看起来不错。我只是想知道如果deleted_table不同步,我该如何重新同步它?你以前用过它们中的任何一个吗? - JasonOng
不,但在软删除的描述中,它提到了内置的辅助方法来保持它们同步。 - Tilendor
简要回顾这两个选项,似乎Acts as soft deletable是更好的选择,无论是使用方法还是维护情况都更好。 - Sam Murray-Sutton

0

PaperTrail 做得很好。有一个不错的Railscast视频介绍,虽然现在有点老了。我知道这个问题已经问了很久,但我出于好奇偶然发现它,想引用一种不错且最新的方法来解决这个问题。


0

这里有一个文件在这里,看起来可以满足你的需求,但我个人认为一定有一些自动过滤已删除记录的东西,除非你特别包含它们。这样,除非你包含重新包括它们的参数或命名范围,否则它们确实会被删除。

不幸的是,我还没有写过这样的东西,而且空闲时间也很有限,但这应该不难,对吧?


0

您可以将已删除的项目移动到单独的集合(或表格等)中 - 然后查看原始列表的任何内容都会发现它已被删除,当方便时,您可以处理新列表。


-1
责任链模式
class Action
{
  Perform(context);
  Undo(context);
}

2
这非常模糊,没有给我任何关于如何实际执行撤销的想法。什么是上下文?它如何与数据库交互? - Tilendor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接