【问题标题】:Rails 4 x paper_trail: keep track of versions after item is destroyedRails 4 x paper_trail:在项目被销毁后跟踪版本
【发布时间】:2015-11-15 17:03:33
【问题描述】:

这是Rails 4 x paper_trail: filter versions by item_id with nested resources 的后续问题。

————

上一个问题的上下文

在我的 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

按照documentation 中的说明,我安装了paper_trail gem 来跟踪我的post 模型上的变化,它就像一个魅力。

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

————

根据my previous question 的回答,我现在的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

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

我想要的是,即使在帖子被销毁后也能跟踪它,包括提到它被销毁的版本。

我怎样才能做到这一点?

【问题讨论】:

  • 也可以尝试为销毁操作定义has_paper_trais?我不确定它是如何工作的,但请尝试has_paper_trail :destroy
  • 我的post 模型中已经有has_paper_trail :on =&gt; [:update, :destroy]。问题不在于paper_trail,而在于我猜的查询,因为我可以跟踪所有版本,包括帖子被销毁的时间,拉动@versions = PaperTrail::Version.order('id DESC').limit(10) 的时间。

标签: ruby-on-rails ruby-on-rails-4 activerecord nested-resources paper-trail-gem


【解决方案1】:

实现这一点的最简单方法是使用Paper Trail's metadata feature 在每个帖子的版本记录中存储相应用户的 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)

【讨论】:

  • 非常感谢安德鲁,这完美解决了问题。
【解决方案2】:

您可以将其标记为已销毁并将其从范围中删除,而不是实际销毁帖子。这将保留其版本历史记录,并允许您在出现错误时恢复“已删除”的帖子。

rails g migration AddDeletedToPosts deleted:boolean

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

澄清

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

【讨论】:

  • 感谢您的回答和建议。这是一个聪明的解决方法,但不完全是我想要的。我最初的查询——@versions = PaperTrail::Version.order('id DESC').limit(10)——允许我在帖子被销毁后跟踪它的版本,但不限于属于用户日历的帖子。新查询——@versions = PaperTrail::Version.where(item_id: Post.where(calendar_id: @calendars.ids)).order('id DESC').limit(10)——则相反。我希望能够同时做到这两点(限制范围并跟踪被破坏的帖子)。这可能吗?
  • 查看我的澄清答案
  • 谢谢。我理解你的推理,这在这个问题的背景下很有意义。但实际上销毁帖子将迫使我们更改应用程序的许多部分。难道我们不能改进查询,使其也考虑已删除的帖子版本吗?
  • 没有。您无法改进查询以实现逻辑上不可能实现的目标。
  • 嘿@Brent Eicher。我只是偶然发现了这篇文章,并认为您可能会感兴趣:leonid.shevtsov.me/en/how-to-use-papertrail-for-soft-deletetion 我还不知道是否可以对我的案例使用类似的查询,但我正在努力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
  • 1970-01-01
  • 2011-06-16
  • 2014-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多