Reputation: 6897
In my Rails 4 app, I am using paper_trail to track changes made by users on the records of the Post
model:
# post.rb
has_paper_trail :on => [:update, :destroy]
A post
belong_to
a calendar
and a calendar
has_many
post
, so I display the changes made to posts in a dashboard located in the calendar
index
view:
<div id="my_changes">
<% if @versions.any? %>
<% @versions.each do |version| %>
<% version.reify ? post = version.reify : post = Post.find_by_id(version.item_id) %>
<p>
<strong>
<% if version.whodunnit.to_i === current_user.id %>
You
<% else %>
<%= User.find_by_id(version.whodunnit).first_name %>
<% end %>
</strong> <%= conjugate(version.event) %> the post "<%= post.subject %>" in the <em><%= link_to Calendar.find_by_id(post.calendar_id).name, calendar_path(id: post.calendar_id) %></em> calendar <span id="update_time_ago">— <%= time_ago_in_words(version.created_at) %> ago.</span></p>
<% end %>
<% else %>
<p>
<span class="glyphicon glyphicon-hand-up" aria-hidden="true"></span><br/>There is no change to your posts yet.<br/>
As soon as you update your calendar, a history of your changes will appear here.
</p>
<% end %>
</div>
This is working fine.
What I would like to achieve now — and I can't figure out how — is not only to display which post has been updated, but also which attribute of the post has been updated and its value.
For instance, instead of:
User_1 updated the post "Test post" in the Test calendar — 3 days ago.
I would like to have something like:
User_1 updated the date / time / subject / copy / of the post "Test post" to NEW_POST_ATTRIBUTE_VALUE in the Test calendar — 3 days ago.
—————
UPDATE: I did read paper_trail
's documentation, in particular the Choose attributes to monitor section, but this does seem to explain how to achieve what I am trying to achieve.
—————
UPDATE 2: I understand that what I am looking for may actually be explained in the Diffing versions section of the documentation.
So, I guess in my index.html.erb
view, I could do something like:
post.versions.last.changeset
But then, how can I extract from there the information that I am interested in, eg: only the attribute that was updated, and its new value, and not the updated_at
attribute, that I cannot ignore
with paper_trail
since I still want to know when the post was updated?
—————
UPDATE 3: in this Stack Overflow thread, @Maysam suggests:
With this behavior enabled, it is reasonably simple to get
object.versions.map{|v| [v.created_at, v.changeset]}
and then iterate over that structure to render your change log.
I am not sure I understand how I can actually iterate over that structure in my case: any suggestion?
—————
Can I actually achieve that with paper_trail?
Upvotes: 2
Views: 2806
Reputation: 17528
.. I would like to .. display .. which attribute of the post has been updated and its value.
Per the documentation on Diffing Versions:
.. to diff adjacent versions .. add an
object_changes
text column to yourversions
table .. PaperTrail will store the changes diff .. in each update version. You can use theversion.changeset
method to retrieve it.
So, once you've done that, try adding
= debug post.versions.last.changeset
To your view. After that, if you know how to work with hashes in ruby, you should be good to go.
Upvotes: 2