Incite Code

Blog of a Rails Developer

Custom Change Messages - Rails Plugin

While working on some code maintenance I noticed a prime opportunity to refactor some code in the spirit of keeping the code DRY. There was code in both the controller action and in mailer methods that created a short paragraph of text describing what fields had been edited on several models for the purposes of both logging this for users to reference later, and to send email notifications.

My solution for this problem was to create a new plugin (custom_change_messages) (EDIT: now converted to a ruby gem) which extends ActiveRecord::Base to provide a few simple methods on instances of your models to generate this text summary of the changes, before the model is saved back to the database (taking advantage of the code in the ActiveRecord::Dirty module). The plugin provides an easy way to customise the messages that are displayed and their format, and handles belongs_to associations nicely as well: Given a Task model that belongs_to a User model, re-assigning a task would produce the message “user has been changed from ‘Jeremy’ to ‘Jordan’” rather than the less informative “user_id has changed from 1 to 2”. See the README for more details on usage.

item.rb
1
2
3
4
5
6
7
8
9
10
11
12
class Item < ActiveRecord::Base
  belongs_to :person

  custom_message_for :person, :display => :username
  custom_message_for :due_on, :as => "Due Date",
  :message => "has been rescheduled", :format => :pretty_print_date

  # 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
items_controller.rb
1
2
3
4
5
6
7
8
9
class ItemsController < ApplicationController

  def update
    @item.attributes = params[:item]
    Mailer.deliver_item_update(@item, @item.change_messages.to_sentence)
    @item.save!
  end

end

Comments