Rails 4 x paper_trail:在物品被销毁后跟踪版本

Rails 4 x paper_trail: keep track of versions after item is destroyed

这是关于 的跟进问题。

——————

前一问题的上下文

在我的 Rails 4 应用程序中,我有以下模型:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
end

class Post < ActiveRecord::Base
    belongs_to :calendar
end

我安装了 paper_trail gem to track changes on my post model as explained in the documentation,它非常有用。

版本显示在 Calendars#Index 视图中,作为用户的仪表板。

——————

根据对 的回答,现在我的 CalendarsController 中有以下代码:

def index
    @user = current_user
    @calendars = @user.calendars.all
    @comments = @user.calendar_comments.order("created_at DESC").limit(20)
    @versions = PaperTrail::Version.where(item_id: Post.where(calendar_id: @calendars.ids)).order('id DESC').limit(10)
end

现在的问题是:当用户销毁 post 时,与此 post 关联的所有版本都会消失。

相反,我想要的是即使 post 被销毁后仍对其进行跟踪,包括提及它已被销毁的版本。

我怎样才能做到这一点?

您可以将其标记为已销毁并将其从作用域中移除,而不是实际销毁 post。这将保留它的版本历史记录,并允许您在出错时恢复 'deleted' post。

rails g migration AddDeletedToPosts deleted:boolean

如果您不再需要 post 及其版本历史记录,例如一段时间后,您可以创建垃圾收集器以永久删除或迁移到单独的存档。

澄清

一个版本只属于它正在跟踪的对象 - 在本例中,一个 post。因此,当你销毁 post 时,你实际上孤立了它的所有版本。是的,它们确实存在于数据库中并且存在于所有版本的查询中,但是您不能再限定它们的范围,因为它们与任何东西都不相关。这就是为什么我建议虚拟地销毁 posts 直到你不再关心它的版本历史。这有意义吗?

实现此目的的最简单方法是使用Paper Trail's metadata feature 在每个post 的版本记录中存储适当的用户ID。换句话说,对您的数据进行一点非规范化以使查询更容易。

class Post < ActiveRecord::Base
  belongs_to :calendar
  has_paper_trail meta: {user_id: :user_ids}  # remember to add a user_id column to the versions table

  def user_ids
    calendar.user_ids  # or whatever you need
  end
end

然后你可以在 CalendarsController:

@versions = PaperTrail::Version.where(user_id: current_user.id)
                               .order('id DESC')
                               .limit(10)