Paper_trail gem abilities
Asked Answered
U

1

4

I was wondering whether the following use case can be achieved using the papertrail gem? A Wikipedia-type of application with wiki pages that logged in users can change/edit and where:

  1. Moderators can undo specific changes:
    I understand papertrail allows to roll back to a previous version but what I’m asking here is somewhat different. That is, the ability to undo a specific edit/change. Suppose there have been three edits/versions to a record/wiki-page. Then if you want to undo edit 2, then changes from edit 1 and 3 should still remain. But if you would roll back to the version before edit 2, then also edit 3 would be undone, which is not what I want here.

  2. Changes made (contributions) by a user feed back into the user’s profile, which would then have an overview of the changes/contributions made by that user:
    I believe this is possible using the --with-changes option (which registers the change that was made in addition to the full dump of the changed resource) in combination with the fact that papertrail registers the user who has made a change. Am I correct in my understanding?
    In the tutorial http://samurails.com/gems/papertrail/ I read about using papertrail in combination with the gem diffy to establish what was changed exactly, but what I don’t understand is why the tutorial uses diffy when papertrail itself already offers a “diffing” functionality?

  3. To have moderators first accept a change by some users, before that change is actually implemented (i.e., before the change is actually applied):
    Can papertrail also help to achieve this functionality?

Unhitch answered 2/9, 2015 at 8:21 Comment(6)
paper_trail is really handy, but when it comes to multi-change-scenario, as you described, i would do it by myself. we use it, just to track changes on ads which needs to be reviewed and accepted or canceled. working smooth. in your case there is a lot of special logic, epsecially whith merging former versions against another former versions. make a changes-table and just track down the changes, everytime a user edited something. that might be easier then to diff it into eachotherLoria
What you're describing sounds a lot like git revert, git diff, and git log. Did you consider using git for persistence? See e.g. the git gem (rubygems.org/gems/git/versions/1.2.9.1)Sociolinguistics
Thanks @Jared, I see you are one of the developers of papertrail. The git gem its documentation I find somewhat hard to read and git also seems to do so much more than I would need. What do you think would be the most effective way to implement the three functionalities: papertrail gem, git gem or to not use a gem and instead implement a changes-table that tracks changes (as huan son suggests)?Unhitch
Moderator approval, and reverting changes from an arbitrary version are not features that PaperTrail provides, so it may be a poor choice. git would be great for reverting, but I'm not sure how you'd implement moderator approval. So, @huanson's suggestion of a custom implementation is probably best.Sociolinguistics
@Unhitch I expanded my answer to cover all topics in your huge question. Please review it below and let me know if something missing in comments.Hon
I posted a follow-up question here: stackoverflow.com/q/32573540Unhitch
H
3

1. Moderators can undo specific changes

You can achieve this functionality using the following module:

module Revertible
   SKIP_FIELDS = [ 'updated_at' ]

   def revert_to(version)
     raise 'not version of this model' unless self == version.item
     changes = version.changeset.select{ |k, v| not SKIP_FIELDS.include?(k) }.map{ |k,v| [k.to_sym, v[0]] }.to_h
     self.update_attributes(changes)
  end
end

It adds revert_to method to the model which allows moderator to undo only changes in specific edit. Pay attention to SKIP_FIELDS array, which excludes several system fields, which should not be reverted.

We can easily test this module. Let's create a table:

create_table :articles do |t|
  t.string :title
  t.string :body

  t.timestamps null: false
end

and associated model:

class Article < ActiveRecord::Base
  include Revertible
  has_paper_trail
end

The following test case shows, that only version specific edits were reverted:

class ArticleTest < ActiveSupport::TestCase
  test "rollback specific edit" do
    article = Article.create(title: 'My Article 1', body: 'first version')
    article.update_attributes(title: 'My Article 1', body: 'second version')
    article.update_attributes(title: 'My Article 3', body: 'third version')

    assert_equal 3, article.versions.count
    assert_equal 'My Article 3', article.title
    assert_equal 'third version', article.body

    article.revert_to article.versions[1]

    assert_equal 4, article.versions.count
    assert_equal 'My Article 3', article.title # title haven't changed
    assert_equal 'first version', article.body # body did change
  end
end

2.Changes made (contributions) by a user

To turn on changes tracking add the following method to your application controller:

class ApplicationController
  def user_for_paper_trail
    user = current_user
    return 'public' if user.blank?
    user.username
  end
end

Changes made by a specific user can be easily tracked now:

versions = PaperTrail::Version.where(whodunnit: 'dimakura')
version = versions.first
version.item # => #<Article id: 1, title: "...", body: "...">
version.event # => "create"
version.changeset

Diffy

As to your question about diffy. You don't actually need it if the only thing you need is to get difference between two adjacent versions. But if you need to compare changes between version separated by several edits, then you do need diffy or any similar library.

Moderator accepts changes

I don't think it's easy to implement in a single field. You probably need to have two columns for "accepted" and "raw" data, maybe even two different models.

I think I covered all you questions and it was helpful for you.

Hon answered 2/9, 2015 at 8:53 Comment(1)
Custom attributes in PT are officially called "metadata", if that helps. See github.com/airblade/paper_trail#storing-metadataSociolinguistics

© 2022 - 2024 — McMap. All rights reserved.