action_tracker.rb
5.05 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require File.join(File.dirname(__FILE__), 'action_tracker_model.rb')
module ActionTracker
  module ControllerMethods
    def self.included(base)
      base.send :user_stamp, ActionTracker::Record
      base.send :extend, ClassMethods
    end
  
    module ClassMethods
      def track_actions_after(verb, options = {}, &block)
        track_actions_by_time(verb, :after, options, &block)
      end
  
      def track_actions_before(verb, options = {}, &block)
        track_actions_by_time(verb, :before, options, &block)
      end
  
      def track_actions(verb, options = {}, &block)
        track_actions_by_time(verb, ActionTrackerConfig.default_filter_time, options, &block)
      end
  
      def track_actions_by_time(verb, time, options = {}, &block)
        keep_params = options.delete(:keep_params) || options.delete('keep_params') || :all
        send("#{time}_filter", options) do |x|
          x.save_action_for_verb(verb.to_s, keep_params)
          block.call(x) unless block.nil?
        end
        send :include, InstanceMethods
      end
    end
  
    module InstanceMethods
      def save_action_for_verb(verb, keep_params = :all)
        if keep_params.is_a? Array
          stored_params = params.reject { |key, value| !keep_params.include?(key.to_sym) and !keep_params.include?(key.to_s) }
        elsif keep_params.to_s == 'none'
          stored_params = {}
        elsif keep_params.to_s == 'all'
          stored_params = params
        end
        user = send ActionTrackerConfig.current_user_method
        tracked_action = case ActionTrackerConfig.verb_type(verb)
          when :groupable
            Record.add_or_create :verb => verb, :user => user, :params => stored_params
          when :updatable
            Record.update_or_create :verb => verb, :user => user, :params => stored_params
          when :single
            Record.new :verb => verb, :user => user, :params => stored_params
        end
        user.tracked_actions << tracked_action
      end
    end
  end
  module ModelMethods
    def self.included(base)
      base.send :extend, ClassMethods
    end
  
    module ClassMethods
      def track_actions(verb, callback, options = {}, &block)
        keep_params = options.delete(:keep_params) || options.delete('keep_params') || :all
        post_proc = options.delete(:post_processing) || options.delete('post_processing') || Proc.new{}
        custom_user = options.delete(:custom_user) || options.delete('custom_user') || nil
        custom_target = options.delete(:custom_target) || options.delete('custom_target') || nil
        send(callback, Proc.new { |tracked| tracked.save_action_for_verb(verb.to_s, keep_params, post_proc, custom_user, custom_target) }, options)
        send :include, InstanceMethods
      end
      def acts_as_trackable(options = {})
        has_many :tracked_actions, { :class_name => "ActionTracker::Record", :order => "updated_at DESC", :foreign_key => :user_id }.merge(options)
        send :include, InstanceMethods
      end
    end
  
    module InstanceMethods
      def time_spent_doing(verb, conditions = {})
        time = 0
        tracked_actions.all(:conditions => conditions.merge({ :verb => verb.to_s })).each do |t| 
          time += t.updated_at - t.created_at
        end
        time.to_f
      end
      def save_action_for_verb(verb, keep_params = :all, post_proc = Proc.new{}, custom_user = nil, custom_target = nil)
        user = self.send(custom_user) unless custom_user.blank?
        user ||= ActionTracker::Record.current_user_from_model
        target = self.send(custom_target) unless custom_target.blank?
        return nil if user.nil?
        if keep_params.is_a? Array
          stored_params = {}
          keep_params.each do |param|
            result = self
            param.to_s.split('.').each { |m| result = result.send(m) }
            stored_params[param.to_s.gsub(/\./, '_')] = result
          end
        elsif keep_params.to_s == 'none'
          stored_params = {}
        elsif keep_params.to_s == 'all'
          stored_params = self.attributes
        end
        tracked_action = case ActionTrackerConfig.verb_type(verb)
          when :groupable
            Record.add_or_create :verb => verb, :params => stored_params, :user => user, :target => target
          when :updatable
            Record.update_or_create :verb => verb, :params => stored_params, :user => user, :target => target
          when :single
            Record.new :verb => verb, :params => stored_params, :user => user
        end
        tracked_action.target = target || self
        user.tracked_actions << tracked_action
        post_proc.call tracked_action.reload
      end
    end
  end
  module ViewHelper
    def describe(ta)
      returning "" do |result|
        if ta.is_a?(ActionTracker::Record)
          result << ta.description.gsub(/\{\{(.*?)\}\}/) { eval $1 }
        else
          result << ""
        end
      end
    end
  end
end
ActionController::Base.send :include, ActionTracker::ControllerMethods
ActiveRecord::Base.send :include, ActionTracker::ModelMethods
ActionView::Base.send :include, ActionTracker::ViewHelper