Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails / Papertrail: Changeset with association changes

I am stuck. I've been trying to figure out how to include the association changes (has_many, has_many through) on a model that has papertrail. I would like to call MyModel.versions.first.changeset and have any changes that took place on associated objects be included in the .changeset hash that is returned from that version of the object.

I've added the migrations for version associations:

class CreateVersionAssociations < ActiveRecord::Migration
  def self.up
    create_table :version_associations do |t|
      t.integer  :version_id
      t.string   :foreign_key_name, :null => false
      t.integer  :foreign_key_id
    end
    add_index :version_associations, [:version_id]
    add_index :version_associations, [:foreign_key_name, :foreign_key_id], :name => 'index_version_associations_on_foreign_key'
  end

  def self.down
    remove_index :version_associations, [:version_id]
    remove_index :version_associations, :name => 'index_version_associations_on_foreign_key'
    drop_table :version_associations
  end
end


class AddTransactionIdColumnToVersions < ActiveRecord::Migration
  def self.up
    add_column :versions, :transaction_id, :integer
    add_index :versions, [:transaction_id]
  end

  def self.down
    remove_index :versions, [:transaction_id]
    remove_column :versions, :transaction_id
  end
end

I have added Papertrail to the associated objects, but as far as I can tell, there is no documentation discussing retrieving changes that took place on the associated objects. Can anyone assist on if this is possible using Papertrail?

I am trying to implement an audit trail of changes on a model and its associated objects that can be accessed in one changeset.

like image 290
heinztomato Avatar asked Aug 11 '15 22:08

heinztomato


1 Answers

The information you need is ultimately stored in the relevant tables versions and version_associations.

However, paper_trail does not provide the methods for you to access the information in the way you want. But you can write a custom method yourself to get a list of the associations's versions of an object.

Let's say you have the following models:

class Article < ApplicationRecord
    has_many :comments
    has_paper_trail
end

class Comment < ApplicationRecord
    belongs_to :article
    has_paper_trail
end

You can find all the comment versions of an article object article this way:

PaperTrail::Version.where(item_type: 'Comment')
                   .joins(:version_associations)
                   .where(version_associations: { foreign_key_name: 'article_id', foreign_key_id: article.id })
                   .order('versions.created_at desc')

You can monkey patch the gem, or define this method as an instance method on the Article class so you can call it easily, eg article.comment_versions

Note, the above information isn't available in the article.versions.first.changeset, because if you change a comment but not the article, the article is not versioned, only the comment is.

But the method above allows you to access the history of changes to the associations.

like image 155
Zack Xu Avatar answered Oct 19 '22 12:10

Zack Xu