module ActivityTracker # :nodoc: def self.included(base) # :nodoc: base.extend ActMethods end module ActMethods # Arguments: # :actor - the user model that owns this object. In most cases this will be :user. Required. # :options - hash of options. # # # Options: # :if - a Proc that determines if the activity should be tracked. # # Examples: # acts_as_activity :user # acts_as_activity :author # acts_as_activity :user, :if => Proc.new{|record| record.post.length > 100 } - will only track the activity if the length of the post is more than 100 def acts_as_activity(actor, options = {}) unless included_modules.include? InstanceMethods after_create do |record| unless options[:if].kind_of?(Proc) and not options[:if].call(record) record.create_activity_from_self end end has_many :activities, :as => :item, :dependent => :destroy class_attribute :activity_options include InstanceMethods end self.activity_options = {:actor => actor} end # This adds a helper method to the model which makes it easy to track actions that can't be associated with an object in the database. # Options: # :actions - An array of actions that are accepted to be tracked. # # Examples: # tracks_unlinked_activities [:logged_in, :invited_friends] - class.track_activity(:logged_in) # def tracks_unlinked_activities(actions = []) unless included_modules.include? InstanceMethods class_attribute :activity_options include InstanceMethods end self.activity_options = {:actions => actions} after_destroy { |record| Activity.destroy_all(:user_id => record.id) } end end module InstanceMethods def create_activity_from_self activity = Activity.new activity.item = self activity.action = self.class.to_s.underscore actor_id = self.send( activity_options[:actor].to_s + "_id" ) activity.user_id = actor_id activity.save end def track_activity(action) if activity_options[:actions].include?(action) activity = Activity.new activity.action = action.to_s activity.user_id = self.id activity.save! else raise "The action #{action} can't be tracked." end end end end