Sometime ago I came across this question on Stack Overflow. The question asks for a way to add a comment to an audit created with the acts_as_audted plugin. At the time I thought it was an interesting problem, and solved it by patching the acts_as_audited plugin during a bout of insomnia.

I feel this is a useful feature worth sharing, and would be content with the patch being accepted into the master repository, but my pull requests have gone ignored. Now I have a need for acts_as_audited with comments in my current project. So, with this patch completed, I’ve decided to bring my fork out of the shadow of its parent.

So on with the details:

The plugin can be found in my github repository. acts_as_audited now adds an accessor attribute, :audit_comment, to the model. When an audit is created it will use the value of model.audit_comment to fill the comment field in the audit.

acts_as_audited also accepts :require_comment as an option now. If given :require_comment => true then any action that would create a new audit is blocked if a comment is missing.

Installation:

script/plugin install git://github.com/EmFi/acts_as_audited.git

Generate the Migration:

If installing acts_as_audited to this project for the first time or you don’t mind wiping out your current audits table:

$  script/generate audited_migration add_audits_table

If updating from a release of acts_as_audited that does not support audit comments and which to keep your audits table:

$  script/generate audited_migration_update update_audits_table

Rake the Migration

$ rake db:migrate

Usage

Usage doesn’t change much from basic acts_as_audited. To add a comment to an audit set the audit_comment attribute before saving/creating/updating a record.

Form Example:

Model:

class Document < ActiveRecord::Base 
  acts_as_audited
end

View

<%form_for (@document) do |f|%>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.text_area :content %>
  <%= f.label :audit_comment %>
  <%= f.audit_comment %>
<% end %>

Controller#update

def update
  @document = Document.find(params[:id])
  @document.update_attributes(params[:document])
  @document.save
end

Example with optional comment:

Model:

class ChessGame < ActiveRecord::Base
   acts_as_audited
   before_validation :populate_audit_comment
 
   protected
   def populate_audit_comment
     comments = []
     comments << "Capture" if piece_captured?
     comments << "Check" if exists_check?
     comments << "Mate" if exists_check_mate?
     self.audit_comments = comments.join("; ")
end

Usage:

@chess_game.update_attributes(:white_queen => "F7")
@chess_game.save
 
Audit.as_user(@user) do 
  @chess_game.audits.last.comments # => "Check"
end

Example with required comment:

Model:

class VeryImportantDocument < ActiveRecord::Base
   acts_as_audited :comment_required => true
end

Usage:

Audit.as_user(@user) do
  @vid = VeryImportantDocument.create(:content => "Lorem Ipsum ....",
    :project_id => 5)
end
@vid.errors #=> {:audit_comment => "Can't be blank"}
@vid.audit_comments = "Authorized by the boss"
@vid.save #=> true