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

六月ゝ 毕业季﹏ 提交于 2019-12-24 12:41:34

问题


This is a follow up question on Rails 4 x paper_trail: filter versions by item_id with nested resources.

—————

CONTEXT FROM PREVIOUS QUESTION

In my Rails 4 app, I have the following models:

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

I installed the paper_trail gem to track changes on my post model as explained in the documentation and it works like a charm.

Versions are displayed in the Calendars#Index view, which serves as a dashboard to the user.

—————

Based on the answer to my previous question, I now have the following code in my 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

Problem is now: when a user destroys a post, all the versions associated with this post disappear.

What I would like instead, is to keep track of a post even after it is destroyed, including the version mentioning that it was destroyed.

How can I achieve that?


回答1:


The simplest way to achieve this is to use Paper Trail's metadata feature to store the appropriate users' ids on each post's version record. In other words, denormalise your data just a little to make querying easier.

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

Then you can do this in your CalendarsController:

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



回答2:


Instead of actually destroying a post, you could just mark it as destroyed and remove it from the scope. This will retain it's version history and allow you to restore a 'deleted' post if a mistake was made.

rails g migration AddDeletedToPosts deleted:boolean

If there's a point where you no longer need a post and it's version history, say after a period of time, you can create a garbage collector for permanent deletion or migration to a separate archive.

Clarification

A version only belongs to the object it is tracking - in this case, a post. As such, when you destroy a post, you are effectively orphaning all of it’s versions. Yes, they do exist in the database and are present in a query of all versions, but you can no longer scope them because they aren’t related to anything. This is why I suggested virtually destroying posts until you no longer care about it’s version history. Does that make any sense?



来源:https://stackoverflow.com/questions/33722350/rails-4-x-paper-trail-keep-track-of-versions-after-item-is-destroyed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!