CustomChangeMessages
CustomChangeMessages is a rails plugin for providing a nicely formatted log message recording any edits made to an active record object. This is based off of the ActiveRecord::Dirty module, making this plugin compatible with rails versions 2.1 and up. There is little to no configuration required, with all columns included by default (except for id, and created_at, updated_at timestamps), and belongs_to associations handled nicely with the default options configurable.
Usage
# In a controllers #update action
def update @post = Post.find(params) @post.attributes = params @changes = @post.change_messages # Use this array to either log history, display in a flash message, or in a mailer. # => [“Title has changed from ‘Ruby on Rails plugin’ to ‘[Update] Ruby on Rails plugin’”, “Category has changed from ‘Ruby’ to ‘Ruby on Rails’”] @post.save! end
API
ActiveRecord extensions:
change_message_for(attribute) # Returns a string message representation of the attribute that has changed change_messages # Returns an array of the messages for each changed attribute
Installation
gem install custom_change_messages
Rails 2.X # config/environment.rb config.gem “custom_change_messages”
Rails 3.X # Gemfile gem “custom_change_messages”
Requirements: active record, version 2.1 or greater, if you use an earlier version you can try using code.bitsweat.net/svn/dirty which backports the ActiveRecord::Dirty code that this gem depends on to earlier rails versions.
Detailed Example
The main use of this is to help clean up controller actions, such as:
class ItemsController < ApplicationController
def update
@item.attributes = params[:item]
Mailer.deliver_item_update(@item, @item..to_sentence)
@item.save!
rescue ActiveRecord::RecordInvalid => e
flash[:error] = e.reord.
redirect_to item_url(@item)
end
#...
end
@item.change_messages.to_sentence will return human readable mesages such as:
> “Description has changed from ‘Nice and easy’ to ‘This task is now rather long and arduous’, User has changed from ‘Jeremy’ to ‘Guy’, and Due Date has been rescheduled from ‘09/11/2008’ to ‘10/11/2008’”
The messages for each attribute are also customizable, which is especially handy for dealing with belongs_to assocations. Here’s a more complicated example:
Use the custom_message_for method to customize the message for the attribute, specifying :display => :name will use the method/attribute :name for displaying the record that the item belongs_to
The skip_message_for method can be used to prevent stop any changes to a particular attribute showing up
class Item < ActiveRecord::Base
belongs_to :person
:person, :display => :username # display the person's username instead of the id
:due_on, :as => "Due Date", :message => "has been rescheduled", :format => :pretty_print_date
# change the syntax of the message for working with dates, because it makes more sense that way
# this method is used for formatting the due_on field when it changes
def pretty_print_date(value = self.due_on)
value.strftime("%d/%m/%Y")
end
end
class Person < ActiveRecord::Base
:username, :as => "Name"
:internal_calculation
end
p = Person.create!(:username => “Jeremy”) p2 = Person.create!(:username => “Optimus Prime”) i = Item.create!(:name => “My Task”, :description => nil, :person => p, :due_on => Date.today) i.attributes = => p2, :description => “This task is difficult, might need some help”
i.change_messages
> [“Due Date has been rescheduled from ‘4/12/2008’ to ‘5/12/2008’”, “Person has changed from ‘Jeremy’ to ‘Optimus Prime’”, “Description has changed from ” to ‘This task is difficult, might need some help’”]
Copyright © 2008 Jeremy Olliver, released under the MIT license