housekeeper-has_activity 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,195 @@
1
+ h1. HasActivity
2
+ ---------------
3
+
4
+ * Originally created by Cary Dunn
5
+ * Modified functionality and additional features by HouseKeeper
6
+
7
+ A simple way to grab recent activity or a sum of values on a given model from a table grouped by day, hour,
8
+ or week with only 1 SQL query and giving the ability to pad the results for days/weeks/hours with no activity.
9
+
10
+ The plugin offers the ability to...
11
+ * Present as a Google Chart (line or bar)
12
+ * Scope your model to given :conditions
13
+ * Pad your results for days with no activity
14
+ * Present your data from a set date until present or between two dates
15
+
16
+ NOTE: MySQL only because of date functions use.
17
+
18
+ "Example Google Chart Generated":http://chart.apis.google.com/chart?cht=bvs&chs=200x50&chd=t:0,10,15,3,8,4,0,3,2,3,0,11,4,23,14,0,0,0,13,0,4,8,19,10,12,21,1&chco=336699&chbh=a,2&chds=0,23&chf=bg,s,EFEFEF&
19
+
20
+ h2. USAGE / INSTALLATION
21
+ ------------------------
22
+
23
+ <pre><code>script/plugin install git://github.com/cdunn/has_activity.git</pre></code>
24
+
25
+ <pre><code>
26
+ class Feed < ActiveRecord::Base
27
+ # Defaults to created_at
28
+ has_activity
29
+
30
+ ...
31
+ end
32
+ </code></pre>
33
+
34
+ <pre><code>
35
+ class Feed < ActiveRecord::Base
36
+ # Change the timestamp DB field to something custom
37
+ has_activity :by => "published_at"
38
+
39
+ ...
40
+ end
41
+ </code></pre>
42
+
43
+ <pre><code>
44
+ # Get all activity since 1 week ago grouped by day (default)
45
+ Feed.activity_since(1.week.ago)
46
+ => [{:activity=>0, :offset=>7, :created_at=>Mon Mar 09 10:27:34 -0700 2009}, {:activity=>0, :offset=>6, :created_at=>Tue Mar 10 10:27:34 -0700 2009}, {:activity=>8, :offset=>5, :created_at=>Wed Mar 11 01:19:09 -0700 2009}, {:activity=>2, :offset=>4, :created_at=>Thu Mar 12 04:26:09 -0700 2009}, {:activity=>0, :offset=>3, :created_at=>Fri Mar 13 10:27:34 -0700 2009}, {:activity=>0, :offset=>2, :created_at=>Sat Mar 14 10:27:34 -0700 2009}, {:activity=>0, :offset=>1, :created_at=>Sun Mar 15 10:27:34 -0700 2009}, {:activity=>0, :offset=>0, :created_at=>Mon Mar 16 10:27:34 -0700 2009}]
47
+ </code></pre>
48
+
49
+ SQL generated for previous statement...
50
+ <pre><code>
51
+ SELECT
52
+ published_at AS timestamp,
53
+ COUNT(*) AS activity_count,
54
+ DATEDIFF(now(), published_at) as days_ago
55
+ FROM feeds
56
+ WHERE 1=1 AND published_at > '2009-03-09 17:27:33'
57
+ GROUP BY days_ago
58
+ ORDER BY published_at ASC
59
+ </code></pre>
60
+
61
+ <pre><code>
62
+ # Get all activity since 1 day ago grouped by hour scoped to a certain user
63
+ Feed.activity_since(1.week.ago, :conditions => ["user_id = ?", current_user.id], :group_by => :hour)
64
+ => [{:activity=>0, :offset=>24, :created_at=>Sun Mar 15 10:29:47 -0700 2009}, {:activity=>0, :offset=>23, :created_at=>Sun Mar 15 11:29:47 -0700 2009}, {:activity=>0, :offset=>22, :created_at=>Sun Mar 15 12:29:47 -0700 2009}, {:activity=>0, :offset=>21, :created_at=>Sun Mar 15 13:29:47 -0700 2009}, {:activity=>0, :offset=>20, :created_at=>Sun Mar 15 14:29:47 -0700 2009}, {:activity=>0, :offset=>19, :created_at=>Sun Mar 15 15:29:47 -0700 2009}, {:activity=>0, :offset=>18, :created_at=>Sun Mar 15 16:29:47 -0700 2009}, {:activity=>0, :offset=>17, :created_at=>Sun Mar 15 17:29:47 -0700 2009}, {:activity=>0, :offset=>16, :created_at=>Sun Mar 15 18:29:47 -0700 2009}, {:activity=>0, :offset=>15, :created_at=>Sun Mar 15 19:29:47 -0700 2009}, {:activity=>0, :offset=>14, :created_at=>Sun Mar 15 20:29:47 -0700 2009}, {:activity=>0, :offset=>13, :created_at=>Sun Mar 15 21:29:47 -0700 2009}, {:activity=>0, :offset=>12, :created_at=>Sun Mar 15 22:29:47 -0700 2009}, {:activity=>0, :offset=>11, :created_at=>Sun Mar 15 23:29:47 -0700 2009}, {:activity=>0, :offset=>10, :created_at=>Mon Mar 16 00:29:47 -0700 2009}, {:activity=>0, :offset=>9, :created_at=>Mon Mar 16 01:29:47 -0700 2009}, {:activity=>0, :offset=>8, :created_at=>Mon Mar 16 02:29:47 -0700 2009}, {:activity=>0, :offset=>7, :created_at=>Mon Mar 16 03:29:47 -0700 2009}, {:activity=>0, :offset=>6, :created_at=>Mon Mar 16 04:29:47 -0700 2009}, {:activity=>0, :offset=>5, :created_at=>Mon Mar 16 05:29:47 -0700 2009}, {:activity=>0, :offset=>4, :created_at=>Mon Mar 16 06:29:47 -0700 2009}, {:activity=>0, :offset=>3, :created_at=>Mon Mar 16 07:29:47 -0700 2009}, {:activity=>0, :offset=>2, :created_at=>Mon Mar 16 08:29:47 -0700 2009}, {:activity=>0, :offset=>1, :created_at=>Mon Mar 16 09:29:47 -0700 2009}, {:activity=>0, :offset=>0, :created_at=>Mon Mar 16 10:29:47 -0700 2009}]\
65
+ </code></pre>
66
+
67
+ SQL generated for previous statement...
68
+ <pre><code>
69
+ SELECT
70
+ published_at AS timestamp,
71
+ COUNT(*) AS activity_count,
72
+ ((((YEAR(now()) - YEAR(published_at))*365)+(DAYOFYEAR(now())-DAYOFYEAR(published_at)))*24)+(HOUR(now())-HOUR(published_at)) as hours_ago,
73
+ CONCAT(YEAR(published_at), CONCAT(DAYOFYEAR(published_at), HOUR(published_at))) AS unique_hour
74
+ FROM feeds
75
+ WHERE user_id = 1 AND published_at > '2009-03-15 17:29:47'
76
+ GROUP BY unique_hour
77
+ ORDER BY published_at ASC
78
+ </code></pre>
79
+
80
+ <pre><code>
81
+ # Get all activity since 2 months ago grouped by week and order it from current week to oldest week
82
+ Feed.activity_since(2.months.ago, :group_by => :week, :order => :desc)
83
+ => [{:activity=>0, :offset=>0, :created_at=>Mon Mar 16 10:34:28 -0700 2009}, {:activity=>0, :offset=>1, :created_at=>Mon Mar 09 10:34:28 -0700 2009}, {:activity=>0, :offset=>2, :created_at=>Mon Mar 02 10:34:28 -0800 2009}, {:activity=>0, :offset=>3, :created_at=>Mon Feb 23 10:34:28 -0800 2009}, {:activity=>0, :offset=>4, :created_at=>Mon Feb 16 10:34:28 -0800 2009}, {:activity=>0, :offset=>5, :created_at=>Mon Feb 09 10:34:28 -0800 2009}, {:activity=>0, :offset=>6, :created_at=>Mon Feb 02 10:34:28 -0800 2009}, {:activity=>0, :offset=>7, :created_at=>Mon Jan 26 10:34:28 -0800 2009}, {:activity=>0, :offset=>8, :created_at=>Mon Jan 19 10:34:28 -0800 2009}]
84
+ </code></pre>
85
+
86
+ SQL generated for previous statement...
87
+ <pre><code>
88
+ SELECT
89
+ published_at AS timestamp,
90
+ COUNT(*) AS activity_count,
91
+ ((YEAR(now()) - YEAR(published_at))*52)+(WEEK(now())-WEEK(published_at)) as weeks_ago,
92
+ YEARWEEK(published_at) AS unique_week
93
+ FROM feeds
94
+ WHERE 1=1 AND published_at > '2009-01-16 17:34:28'
95
+ GROUP BY unique_week
96
+ ORDER BY published_at ASC
97
+ </code></pre>
98
+
99
+ <pre><code>
100
+ # Get Usd Net Commission in July ago grouped by day and order it in ascending order by the days commission was earnt on for account_id 1
101
+ AccountPnl.activity_between(july_month.beginning_of_month,
102
+ july_month.end_of_month,
103
+ :group_by => :day,
104
+ :padding => false,
105
+ :sum_on => "usd_net_commission",
106
+ :conditions => ["crm_account_id=?", 1],
107
+ :order => :asc)
108
+ </code></pre>
109
+
110
+ SQL generated for previous statement...
111
+ <pre><code>
112
+ SELECT
113
+ earnt_on AS timestamp,
114
+ COUNT(*) AS activity_count, SUM(usd_net_commission) as sum,
115
+ DATEDIFF('2009-07-31 23:59:59', earnt_on) as days_ago
116
+ FROM crm_daily_account_pnls
117
+ WHERE crm_account_id=16 AND earnt_on
118
+ BETWEEN '2009-07-01 00:00:00' AND '2009-07-31 23:59:59'
119
+ GROUP BY days_ago
120
+ ORDER BY earnt_on ASC
121
+ </code></pre>
122
+
123
+
124
+ h2. CONVERT DATA INTO GOOGLE CHART
125
+
126
+ <pre><code>
127
+ Feed.activity_since(6.months.ago, :group_by => :week, :order => :desc).to_activity_gchart
128
+ => "http://chart.apis.google.com/chart?cht=bvs&chs=200x50&chd=t:0,10,15,3,8,4,0,3,2,3,0,11,4,23,14,0,0,0,13,0,4,8,19,10,12,21,1&chco=336699&chbh=a,2&chds=0,23&chf=bg,s,EFEFEF&"
129
+ </code></pre>
130
+
131
+ <pre><code>
132
+ Feed.activity_since(6.months.ago, :group_by => :week, :order => :desc).to_activity_gchart
133
+ AccountPnl.activity_between(july_month.beginning_of_month,
134
+ july_month.end_of_month,
135
+ :group_by => :day,
136
+ :padding => false,
137
+ :sum_on => "usd_net_commission",
138
+ :conditions => ["crm_account_id=?", 1],
139
+ :order => :asc).to_activity_gchart( :type => :line,
140
+ :column => :sum,
141
+ :size => "100x45",
142
+ :bgcolor => "f0ffdc",
143
+ :chart_color => "D1EAFF",
144
+ :area_color => "DFEBFF",
145
+ :line_color => "c7c7c7",
146
+ :line_width => "4"))
147
+ => "http://chart.apis.google.com/chart?chs=100x45&cht=ls&chco=c7c7c7&chm=B,DFEBFF,0,0,0&chd=t:<data>&chds=0,0&chf=bg,s,f0ffdc&"
148
+ </code></pre>
149
+
150
+ h2. OTHER OPTIONS
151
+
152
+ <pre><code>
153
+ # Grabs a hash of the activity since <time ago> grouped by <hour/day/week>
154
+ #
155
+ # * :conditions
156
+ # same as the standard Rails finder. Used to scope your activity to a particular user, etc.
157
+ # * :padding
158
+ # true/false
159
+ # * :group_by
160
+ # :hour, :day, :week
161
+ #
162
+ def activity_since(since=1.week.ago, options={})
163
+ </code></pre>
164
+
165
+ <pre><code>
166
+ # Returns a URL to a simple google chart the represents the activity returned by the plugin
167
+ #
168
+ # * :type => :bar/:line
169
+ # * :size => "200x50"
170
+ # * :bgcolor => "EFEFEF"
171
+ # * :chart_color => "336699"
172
+ # * :area_color => "DFEBFF" (only for :line)
173
+ # * :line_color => "0077CC" (only for :line)
174
+ # * :line_width => "2" (only for :line)
175
+ #
176
+ def to_activity_gchart(options={})
177
+ </code></pre>
178
+
179
+ h2. INDEX THE TIMESTAMP YOU USE
180
+
181
+ Obviously there is not "one index fits all" but you should include an index on at least the timestamp that fits the conditions you are using.
182
+ The same applies when performing SUM on a column.
183
+ <pre><code>
184
+ add_index :model, [:created_at]
185
+ </code></pre>
186
+
187
+ h2. NOTES
188
+
189
+ * Using sum and creating Bar Charts is not fully tested - HouseKeeper
190
+ * Some work still needs to be done on the queries and a tidy up of has_activity.rb
191
+
192
+ Copyright (c) 2009 Cary Dunn <cary.dunn@gmail.com> "http://elctech.com":http://elctech.com, released under the MIT license
193
+ Modified by HouseKeeper
194
+ - Added the ability to sum a column - giving you a total ammount from a date until now or between 2 dates
195
+ - Added Between functionality so you can get activity or sums between 2 specified dates
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the has_activity plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the has_activity plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'HasActivity'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 4
4
+ :patch: 0
5
+
@@ -0,0 +1,50 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{has_activity}
5
+ s.version = "0.4.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Cary Dunn", "Carl Burton"]
9
+ s.date = %q{2009-09-17}
10
+ s.description = %q{A simple way to grab recent activity or a columns sum on a given model from a table grouped by day, hour, or week with only 1 SQL query and giving the ability to pad the results for days/weeks/hours with no activity.}
11
+ s.email = %q{carl@house-keeping.com}
12
+ s.extra_rdoc_files = [
13
+ "README.textile"
14
+ ]
15
+ s.files = [
16
+ "VERSION.yml",
17
+ "uninstall.rb",
18
+ "README.textile",
19
+ "Rakefile",
20
+ "MIT-LICENSE",
21
+ "install.rb",
22
+ "init.rb",
23
+ "has_activity.gemspec",
24
+ "test/test_helper.rb",
25
+ "test/has_activity_test.rb",
26
+ "tasks/has_activity_tasks.rake",
27
+ "lib/has_activity.rb",
28
+ "lib/core_ext.rb"
29
+ ]
30
+ s.has_rdoc = false
31
+ s.homepage = %q{http://github.com/housekeeper/has_activity}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.1}
35
+ s.summary = %q{A simple way to grab recent activity or a columns sum on a given model from a table grouped by day, hour, or week with only 1 SQL query and giving the ability to pad the results for days/weeks/hours with no activity.}
36
+ s.test_files = [
37
+ "test/test_helper.rb",
38
+ "test/has_activity_test.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 2
44
+
45
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ else
47
+ end
48
+ else
49
+ end
50
+ end
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ # Include hook code here
2
+ require 'has_activity'
3
+ ActiveRecord::Base.send(:include, Elctech::Has::Activity)
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
data/lib/core_ext.rb ADDED
@@ -0,0 +1,53 @@
1
+ # Original Author Cary Dunn <cary.dunn@gmail.com>
2
+ # Modified by HouseKeeper
3
+
4
+ unless Array.instance_methods.include? 'to_activity_gchart'
5
+ Array.class_eval do
6
+ # Returns a URL to a simple google chart the represents the activity returned by the plugin
7
+ #
8
+ # * :type => :bar/:line
9
+ # * :column => :activity/:sum
10
+ # * :size => "200x50"
11
+ # * :bgcolor => "EFEFEF"
12
+ # * :chart_color => "336699"
13
+ # * :area_color => "DFEBFF" (only for :line)
14
+ # * :line_color => "0077CC" (only for :line)
15
+ # * :line_width => "2" (only for :line)
16
+ #
17
+ def to_activity_gchart(options={})
18
+ options[:type] ||= :graph
19
+ options[:column] ||= :activity
20
+ options[:size] ||= "200x50"
21
+ options[:bgcolor] ||= "EFEFEF"
22
+ options[:chart_color] ||= "336699"
23
+ options[:area_color] ||= "DFEBFF"
24
+ options[:line_color] ||= "0077CC"
25
+ options[:line_width] ||= "2"
26
+
27
+ case options[:column]
28
+ when :activity
29
+ activity_min_data_point = self.min{|a,b| a[:activity] <=> b[:activity] }[:activity]
30
+ activity_max_data_point = self.max{|a,b| a[:activity] <=> b[:activity] }[:activity]
31
+ activity_str = self.map{|a| a[:activity]}.join(",")
32
+ return generate_url(activity_str, activity_min_data_point, activity_max_data_point, options)
33
+ when :sum
34
+ sum_min_data_point = self.min{|a,b| a[:sum] <=> b[:sum] }[:sum]
35
+ sum_max_data_point = self.max{|a,b| a[:sum] <=> b[:sum] }[:sum]
36
+ sum_str = self.map{|a| a[:sum]}.join(",")
37
+ return generate_url(sum_str, sum_min_data_point, sum_max_data_point, options)
38
+ end
39
+
40
+ end
41
+
42
+ private
43
+
44
+ def generate_url(data, min_data_point, max_data_point, options={})
45
+ if options[:type] == :line
46
+ return "http://chart.apis.google.com/chart?chs=#{options[:size]}&cht=ls&chco=#{options[:line_color]}&chm=B,#{options[:area_color]},0,0,0&chd=t:#{data}&chds=#{min_data_point},#{max_data_point}&chf=bg,s,#{options[:bgcolor]}&"
47
+ else
48
+ return "http://chart.apis.google.com/chart?cht=bvs&chs=#{options[:size]}&chd=t:#{data}&chco=#{options[:chart_color]}&chbh=a,#{options[:line_width]}&chds=#{min_data_point},#{max_data_point}&chf=bg,s,#{options[:bgcolor]}&"
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,232 @@
1
+ #
2
+ # => has_activity
3
+ # => Cary Dunn <cary.dunn@gmail.com>
4
+ # => Modified by HouseKeeper: added between methods and sum option
5
+
6
+ # HasActivity
7
+
8
+ require 'core_ext'
9
+
10
+ module Elctech
11
+ module Has #:nodoc:
12
+ module Activity #:nodoc:
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+
17
+ module ClassMethods
18
+
19
+ def self.extended(base)
20
+ base.class_inheritable_accessor :activity_options
21
+ end
22
+
23
+ def has_activity(options={})
24
+ options[:by] ||= "created_at"
25
+ include Elctech::Has::Activity::InstanceMethods
26
+ extend Elctech::Has::Activity::SingletonMethods
27
+
28
+ self.activity_options = options
29
+ end
30
+ end
31
+
32
+ module SingletonMethods
33
+
34
+ # Grabs a hash of the activity between <time a> AND <time b>grouped by <hour/day/week>
35
+ #
36
+ # * :conditions
37
+ # same as the standard Rails finder. Used to scope your activity to a particular user, etc.
38
+ # * :padding
39
+ # true/false
40
+ # * :group_by
41
+ # :hour, :day, :week
42
+ #
43
+ def activity_between(between=1.week.ago, andbetween=Time.now.utc, options={})
44
+ activity_scope = (options.has_key?(:conditions) ? sanitize_sql(options[:conditions]) : "1=1")
45
+ options[:padding] ||= true
46
+ options[:order] ||= :asc
47
+ options[:group_by] ||= :day
48
+ sum = options[:sum_on] ? "SUM(#{options[:sum_on]}) as sum," : ""
49
+
50
+ case options[:group_by]
51
+ when :hour
52
+ sql_statement = sanitize_sql(
53
+ ["SELECT
54
+ #{activity_options[:by]} AS timestamp,
55
+ COUNT(*) AS activity_count, #{sum}
56
+ ((((YEAR(now()) - YEAR(#{activity_options[:by]}))*365)+(DAYOFYEAR(now())-DAYOFYEAR(#{activity_options[:by]})))*24)+(HOUR(now())-HOUR(#{activity_options[:by]})) as hours_ago,
57
+ CONCAT(YEAR(#{activity_options[:by]}), CONCAT(DAYOFYEAR(#{activity_options[:by]}), HOUR(#{activity_options[:by]}))) AS unique_hour
58
+ FROM #{self.table_name}
59
+ WHERE #{activity_scope} AND #{activity_options[:by]} > ?
60
+ GROUP BY unique_hour
61
+ ORDER BY #{activity_options[:by]} ASC",
62
+ between.to_s(:db)
63
+ ]
64
+ )
65
+ unit = "hours_ago"
66
+ oldest_possible_unit = ((andbetween-between)/60)/60
67
+ when :week
68
+ sql_statement = sanitize_sql(
69
+ ["SELECT
70
+ #{activity_options[:by]} AS timestamp,
71
+ COUNT(*) AS activity_count, #{sum}
72
+ ((YEAR(now()) - YEAR(#{activity_options[:by]}))*52)+(WEEK(now())-WEEK(#{activity_options[:by]})) as weeks_ago,
73
+ YEARWEEK(#{activity_options[:by]}) AS unique_week
74
+ FROM #{self.table_name}
75
+ WHERE #{activity_scope} AND #{activity_options[:by]}
76
+ BETWEEN ? AND ?
77
+ GROUP BY unique_week
78
+ ORDER BY #{activity_options[:by]} ASC",
79
+ between.to_s(:db),andbetween.to_s(:db)
80
+ ]
81
+ )
82
+ unit = "weeks_ago"
83
+ oldest_possible_unit = ((((andbetween-between)/60)/60)/24)/7
84
+ else
85
+ sql_statement = sanitize_sql(
86
+ ["SELECT
87
+ #{activity_options[:by]} AS timestamp,
88
+ COUNT(*) AS activity_count, #{sum}
89
+ DATEDIFF('#{andbetween.to_s(:db)}', #{activity_options[:by]}) as days_ago
90
+ FROM #{self.table_name}
91
+ WHERE #{activity_scope} AND #{activity_options[:by]}
92
+ BETWEEN ? AND ?
93
+ GROUP BY days_ago
94
+ ORDER BY #{activity_options[:by]} ASC",
95
+ between.to_s(:db), andbetween.to_s(:db)
96
+ ]
97
+ )
98
+ unit = "days_ago"
99
+ oldest_possible_unit = (((andbetween-between)/60)/60)/24
100
+ end
101
+
102
+ results = connection.select_all(sql_statement)
103
+ (options[:padding] ? pad_activity_results(results, unit, oldest_possible_unit.round, options[:order]) : format_activity_results(results, unit, order))
104
+ end
105
+
106
+ # Grabs a hash of the activity since <time ago> grouped by <hour/day/week>
107
+ #
108
+ # * :conditions
109
+ # same as the standard Rails finder. Used to scope your activity to a particular user, etc.
110
+ # * :padding
111
+ # true/false
112
+ # * :group_by
113
+ # :hour, :day, :week
114
+ #
115
+ def activity_since(since=1.week.ago, options={})
116
+ activity_scope = (options.has_key?(:conditions) ? sanitize_sql(options[:conditions]) : "1=1")
117
+ options[:padding] ||= true
118
+ options[:order] ||= :asc
119
+ options[:group_by] ||= :day
120
+ sum = options[:sum_on] ? "SUM(#{options[:sum_on]}) as sum," : ""
121
+
122
+ case options[:group_by]
123
+ when :hour
124
+ sql_statement = sanitize_sql(
125
+ ["SELECT
126
+ #{activity_options[:by]} AS timestamp,
127
+ COUNT(*) AS activity_count, #{sum}
128
+ ((((YEAR(now()) - YEAR(#{activity_options[:by]}))*365)+(DAYOFYEAR(now())-DAYOFYEAR(#{activity_options[:by]})))*24)+(HOUR(now())-HOUR(#{activity_options[:by]})) as hours_ago,
129
+ CONCAT(YEAR(#{activity_options[:by]}), CONCAT(DAYOFYEAR(#{activity_options[:by]}), HOUR(#{activity_options[:by]}))) AS unique_hour
130
+ FROM #{self.table_name}
131
+ WHERE #{activity_scope} AND #{activity_options[:by]} > ?
132
+ GROUP BY unique_hour
133
+ ORDER BY #{activity_options[:by]} ASC",
134
+ since.to_s(:db)
135
+ ]
136
+ )
137
+ unit = "hours_ago"
138
+ oldest_possible_unit = ((Time.now-since)/60)/60
139
+ when :week
140
+ sql_statement = sanitize_sql(
141
+ ["SELECT
142
+ #{activity_options[:by]} AS timestamp,
143
+ COUNT(*) AS activity_count, #{sum}
144
+ ((YEAR(now()) - YEAR(#{activity_options[:by]}))*52)+(WEEK(now())-WEEK(#{activity_options[:by]})) as weeks_ago,
145
+ YEARWEEK(#{activity_options[:by]}) AS unique_week
146
+ FROM #{self.table_name}
147
+ WHERE #{activity_scope} AND #{activity_options[:by]} > ?
148
+ GROUP BY unique_week
149
+ ORDER BY #{activity_options[:by]} ASC",
150
+ since.to_s(:db)
151
+ ]
152
+ )
153
+ unit = "weeks_ago"
154
+ oldest_possible_unit = ((((Time.now-since)/60)/60)/24)/7
155
+ else
156
+ sql_statement = sanitize_sql(
157
+ ["SELECT
158
+ #{activity_options[:by]} AS timestamp,
159
+ COUNT(*) AS activity_count, #{sum}
160
+ DATEDIFF(now(), #{activity_options[:by]}) as days_ago
161
+ FROM #{self.table_name}
162
+ WHERE #{activity_scope} AND #{activity_options[:by]} > ?
163
+ GROUP BY days_ago
164
+ ORDER BY #{activity_options[:by]} ASC",
165
+ since.to_s(:db)
166
+ ]
167
+ )
168
+ unit = "days_ago"
169
+ oldest_possible_unit = (((Time.now-since)/60)/60)/24
170
+ end
171
+
172
+ results = connection.select_all(sql_statement)
173
+ (options[:padding] ? pad_activity_results(results, unit, oldest_possible_unit.round, options[:order]) : format_activity_results(results, unit, order))
174
+ end
175
+
176
+ private
177
+ def format_activity_results(results, unit, order)
178
+ results.inject([]) do |rs,r|
179
+ entry = {
180
+ :offset => r[unit].to_i,
181
+ :activity => r["activity_count"].to_i,
182
+ :sum => r["sum"].to_f,
183
+ :date => Time.parse(r["timestamp"])
184
+ }
185
+ (order == :asc) ? rs.push(entry) : rs.unshift(entry)
186
+ end
187
+ end
188
+
189
+ def pad_activity_results(results, unit, oldest_possible_offset, order)
190
+ padded_results = []
191
+
192
+ current_unit_offset = oldest_possible_offset
193
+ current_result_index = 0
194
+
195
+ while current_unit_offset >= 0 do
196
+ if current_result_index < results.size && results[current_result_index][unit].to_i == current_unit_offset
197
+ entry = {
198
+ :offset => current_unit_offset,
199
+ :activity => results[current_result_index]["activity_count"].to_i,
200
+ :sum => results[current_result_index]["sum"].to_f,
201
+ :created_at => Time.parse(results[current_result_index]["timestamp"])
202
+ }
203
+ current_result_index = current_result_index+1
204
+ else
205
+ case unit
206
+ when "hours_ago"
207
+ created_at_given_offset = Time.now-current_unit_offset.hours
208
+ when "weeks_ago"
209
+ created_at_given_offset = Time.now-current_unit_offset.weeks
210
+ else
211
+ created_at_given_offset = Time.now-current_unit_offset.days
212
+ end
213
+ entry = {
214
+ :offset => current_unit_offset,
215
+ :activity => 0,
216
+ :sum => 0,
217
+ :created_at => created_at_given_offset
218
+ }
219
+ end
220
+ current_unit_offset = current_unit_offset-1
221
+ (order == :asc) ? padded_results.push(entry) : padded_results.unshift(entry)
222
+ end
223
+
224
+ padded_results
225
+ end
226
+ end
227
+
228
+ module InstanceMethods;end
229
+
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :has_activity do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class HasActivityTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: housekeeper-has_activity
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Cary Dunn
8
+ - Carl Burton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-09-17 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: A simple way to grab recent activity or a columns sum on a given model from a table grouped by day, hour, or week with only 1 SQL query and giving the ability to pad the results for days/weeks/hours with no activity.
18
+ email: carl@house-keeping.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README.textile
25
+ files:
26
+ - VERSION.yml
27
+ - uninstall.rb
28
+ - README.textile
29
+ - Rakefile
30
+ - MIT-LICENSE
31
+ - install.rb
32
+ - init.rb
33
+ - has_activity.gemspec
34
+ - test/test_helper.rb
35
+ - test/has_activity_test.rb
36
+ - tasks/has_activity_tasks.rake
37
+ - lib/has_activity.rb
38
+ - lib/core_ext.rb
39
+ has_rdoc: false
40
+ homepage: http://github.com/housekeeper/has_activity
41
+ licenses:
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.5
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: A simple way to grab recent activity or a columns sum on a given model from a table grouped by day, hour, or week with only 1 SQL query and giving the ability to pad the results for days/weeks/hours with no activity.
66
+ test_files:
67
+ - test/test_helper.rb
68
+ - test/has_activity_test.rb