Userstamp
Userstamp extends ActiveRecord::Base to add automatic updating of ‘creator’, ‘updater’, and ‘deleter’ attributes. It is based loosely on the ActiveRecord::Timestamp module.
Two class methods (model_stamper
and stampable
) are implemented in this plugin. The model_stamper
method is used in models that are responsible for creating, updating, or deleting other objects. The stampable
method is used in models that are subject to being created, updated, or deleted by ‘stampers’.
- As Rails plugin: `script/plugin install git://github.com/delynn/userstamp.git ` - As gem: ` sudo gem install userstamp `
The assumption is that you have two different categories of objects; those that manipulate, and those that are manipulated. For those objects that are being manipulated there’s the Stampable module and for the manipulators there’s the Stamper module. There’s also the actual Userstamp module for your controllers that assists in setting up your environment on a per request basis.
Assume a weblog application has User and Post objects. # 1: Create the migrations for these objects
class CreateUsers < ActiveRecord::Migration def self.up create_table :users, :force => true do |t| ... t.userstamps # use t.userstamps(true) if you also want 'deleter_id' end end def self.down drop_table :users end end class CreatePosts < ActiveRecord::Migration def self.up create_table :posts, :force => true do |t| ... t.userstamps # use t.userstamps(true) if you also want 'deleter_id' end end def self.down drop_table :posts end end
# 2: Users are going to manipulate Post’s, use the model_stamper
:
class User < ActiveRecord::Base model_stamper end
# 3: Set the current user in the ApplicationController:
class ApplicationController < ActionController::Base include Userstamp end
If all you are interested in is making sure all tables that have the proper columns are stamped by the currently logged in user you can stop right here. More than likely you want all your associations setup on your stamped objects, and that’s where the stampable
class method comes in. So in our example we’ll want to use this method in both our User and Post classes:
class User < ActiveRecord::Base model_stamper stampable end class Post < ActiveRecord::Base stampable end
Okay, so what all have we done? The model_stamper
class method injects two methods into the User class. They are #stamper= and #stamper and look like this:
def stamper=(object) object_stamper = if object.is_a?(ActiveRecord::Base) object.send("#{object.class.primary_key}".to_sym) else object end Thread.current["#{self.to_s.downcase}_#{self.object_id}_stamper"] = object_stamper end def stamper Thread.current["#{self.to_s.downcase}_#{self.object_id}_stamper"] end
The stampable
method allows you to customize what columns will get stamped, and also creates the creator
, updater
, and deleter
associations.
The Userstamp module that we included into our ApplicationController uses the setter method to set which user is currently making the request. By default the ‘set_stampers’ method works perfectly with the RestfulAuthentication plug-in:
def set_stampers User.stamper = self.current_user end
If you aren’t using ActsAsAuthenticated, then you need to create your own version of the set_stampers
method in the controller where you’ve included the Userstamp module.
Now, let’s get back to the Stampable module (since it really is the interesting one). The Stampable module sets up before_* filters that are responsible for setting those attributes at the appropriate times. It also creates the belongs_to relationships for you.
If you need to customize the columns that are stamped, the stampable
method can be completely customized. Here’s an quick example:
class Post < ActiveRecord::Base stampable :stamper_class_name => :person, :creator_attribute => :create_user, :updater_attribute => :update_user, :deleter_attribute => :delete_user end
# config/environment.rb Ddb::Userstamp.compatibility_mode = true
All: rake One: ruby test/compatibility_stamping_test.rb
The original idea for this plugin came from the Rails Wiki article entitled Extending ActiveRecord.