Search code examples
ruby-on-railsruby-on-rails-4activerecordnested-resourcespaper-trail-gem

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


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?


Solution

  • 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)