Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use papertrail to store "pending-approval" changes?

I need to allow less-privileged users to propose changes to a record but have them sit somewhere until an administrator approves them. It should be similar to the way Stack Overflow allows users with lower reputation to propose an edit to a question or answer which must be reviewed by someone with higher reputation.

In papertrail terms, I'd like to allow users to create versions of a record without actually committing those changes to the record itself—future versions, rather than past versions. Then I'd like to allow another user to "revert" ("prevert"?) to the new version.

Is this something papertrail supports? Or is there another gem that can do this?

like image 651
Peeja Avatar asked Feb 24 '14 22:02

Peeja


2 Answers

I know that this question is very old but let me explain how I managed to solve it:

Suppose that I have a model Post, two users: A and B, that A is authorized to update posts but he needs B approval before committing the changes, B is the monitor who can approve updates and can update posts as well.

  1. I added a method to revert the record to a particular version of it so we can update it with whatever version we want:
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[1]] }.to_h
    self.update_attributes(changes)
end

I got that method from this Stackoverflow answer but I modified it a bit.

  1. The trick is to not update the record itself if the current user A hasn't authorized to commit changing, rather than updating, a new Paper Trail version will be created, then the monitor B can accept the new changes by reverting the original record to that version.

For that I used a function from Paper Trail core paper_trail.record_update().

A:

p = Post.find(1)
p.title = "A new pending version"
p.paper_trail.record_update(nil)

B as a monitor:

p = Publication.find(1)
p.revert_to(p.versions.last)

B as an editor:

p = Publication.find(1)
p.title = "p will be updated to this version immediately"
p.paper_trail.record_update(nil)
p.save
  1. I added has_paper_trail to Post model but I restricted it on create and destroy actions because as I said above I don't want a new version to be created after updating, I want it to be created before.
has_paper_trail :on => [:create, :destroy]
like image 70
Ehsan Avatar answered Oct 11 '22 20:10

Ehsan


I'm facing the same problem right now.

No, it's not supported by paper_trail, but maybe we can achieve it adding an approved attribute to our Record. It should default to false so that, when the Record object is saved, a new paper_trail version is created with that attribute set to false. Later an AdminUser can approve the record setting approved to true and paper_trail will create the new approved version.

It's not the cleanest solution but it should work. And we could also add other attributes to your Record model such as approved_by and approved_at, should you we them.

Mmm.. I'm thinking about it..

Please let me know if you found a better solution!

like image 37
Darme Avatar answered Oct 11 '22 18:10

Darme