ref: master
vendor/plugins/action_tracker/lib/action_tracker_model.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
module ActionTracker class Record < ActiveRecord::Base attr_accessible :verb, :params, :user, :target self.table_name = 'action_tracker' belongs_to :user, :polymorphic => true belongs_to :target, :polymorphic => true alias :profile :user serialize :params, Hash before_validation :stringify_verb validates_presence_of :verb validates_presence_of :user validate :user_existence def user_existence errors.add(:user, "user doesn't exists") if user && !user.class.exists?(user) end alias_method :subject, :user # In days RECENT_DELAY = 30 scope :recent, -> { where 'created_at >= ?', RECENT_DELAY.days.ago } scope :visible, -> { where visible: true } def self.current_user ActionTrackerConfig.current_user.call end def self.update_or_create(params) u = params[:user] || current_user return if u.nil? target_hash = params[:target].nil? ? {} : {:target_type => params[:target].class.base_class.to_s, :target_id => params[:target].id} conditions = { :user_id => u.id, :user_type => u.class.base_class.to_s, :verb => params[:verb].to_s }.merge(target_hash) l = where(conditions).last ( !l.nil? and Time.now - l.updated_at < ActionTrackerConfig.timeout ) ? l.update(params.merge({ :updated_at => Time.now })) : l = new(params) l end def self.add_or_create(params) u = params[:user] || current_user return if u.nil? target_hash = params[:target].nil? ? {} : {:target_type => params[:target].class.base_class.to_s, :target_id => params[:target].id} l = where({user_id: u.id, user_type: u.class.base_class.to_s, verb: params[:verb].to_s}.merge target_hash).last if !l.nil? and Time.now - l.created_at < ActionTrackerConfig.timeout params[:params].clone.each { |key, value| params[:params][key] = l.params[key].clone.push(value) } l.update params else params[:params].clone.each { |key, value| params[:params][key] = [value] } l = new params end l end def self.time_spent(conditions = {}) # In seconds #FIXME Better if it could be completely done in the database, but SQLite does not support difference between two timestamps time = 0 self.where(conditions).each{ |action| time += action.updated_at - action.created_at } time.to_f end def duration # In seconds ( updated_at - created_at ).to_f end def description text = ActionTrackerConfig.get_verb(self.verb)[:description] || "" if text.is_a?(Proc) self.instance_exec(&text) else text end end def describe description.gsub(/\{\{([^}]+)\}\}/) { eval $1 } end def predicate self.params || {} end def phrase { :subject => self.subject, :verb => self.verb, :predicate => self.predicate } end def method_missing(method, *args, &block) if method.to_s =~ /^get_(.*)$/ param = method.to_s.gsub('get_', '') predicate[param.to_s] || predicate[param.to_sym] else super end end def collect_group_with_index(param) send("get_#{param}").collect.with_index{ |el, i| yield el, i } end protected def validate errors.add_to_base "Verb must be one of the following: #{ActionTrackerConfig.verb_names.join(',')}" unless ActionTrackerConfig.verb_names.include?(self.verb) end private def stringify_verb self.verb = self.verb.to_s unless self.verb.nil? end end end |