has-activity 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "rdoc", "~> 3.12"
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.8.3"
13
+ gem "simplecov", ">= 0"
14
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Cary Dunn
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/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.rdoc ADDED
@@ -0,0 +1,47 @@
1
+ = has-activity
2
+
3
+ == Intro
4
+
5
+ A simple way to grab recent activity on a given model grouped by hour, day, week or month (time series). Supports "padding" for intervals without activity.
6
+
7
+ == Usage
8
+
9
+ Add the activity functionality to a model...
10
+
11
+ # app/models/user.rb
12
+ has_activity :on => :created_at
13
+
14
+ Query for activity...
15
+
16
+ # Calculate activity from 1 month ago, grouped by each day, for active users...
17
+ User.where("active = 1").activity_since(1.month.ago, :by => :day)
18
+ => [{ :offset => 31, :activity => 5, :timestamp => 2012-03-18 17:00:00 -0700 }, { :offset => 30, :activity => 12, :timestamp => 2012-03-17 17:00:00 -0700 }, ... ]
19
+
20
+ # Other examples...
21
+
22
+ # Calculate the new users per hour in the last day...
23
+ User.activity_since(1.day.ago, :by => :hour)
24
+
25
+ # Calculate the new users per week for January of 2012...
26
+ User.activity_between(Date.parse("2012-01-01"), Date.parse("2012-01-31"), :by => :week)
27
+
28
+ Graph the data...
29
+
30
+ # Google charts sparkline...
31
+ User.activity_since(1.day.ago, :by => :hour).to_activity_gchart
32
+ => http://chart.apis.google.com/chart?chs=200x50&cht=ls&chco=0077CC&chm=B,DFEBFF,0,0,0&chd=t:17,252,105,80,25,99,333,39,98,17,252,105,80,25,99,333,39,98&chds=0,333&chf=bg,s,EFEFEF&
33
+
34
+ # D3 charts...
35
+ soon...
36
+
37
+ # Or create your own...
38
+ data = User.activity_since(Date.today.beginning_of_month, :by => :day)
39
+ data.collect { |d|
40
+ [d[:activity], d[:timestamp].strftime("%d/%m (%A)")]
41
+ }
42
+ => [[5, "1/1 (Tuesday)"], [12, "1/2 (Wednesday)"], [33, "1/3 (Thursday)"], ...]
43
+
44
+ == Copyright
45
+
46
+ Copyright (c) 2012 Cary Dunn. See LICENSE.txt for
47
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "has-activity"
18
+ gem.homepage = "http://github.com/cdunn/has_activity"
19
+ gem.license = "MIT"
20
+ gem.summary = "A simple way to grab recent activity on a given model grouped by hour, day, week or month (time series)."
21
+ gem.description = "A simple way to grab recent activity on a given model grouped by hour, day, week or month (time series). Supports \"padding\" for intervals without activity."
22
+ gem.email = "cary.dunn@gmail.com"
23
+ gem.authors = ["Cary Dunn"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "has-activity"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Cary Dunn"]
12
+ s.date = "2012-04-19"
13
+ s.description = "A simple way to grab recent activity on a given model grouped by hour, day, week or month (time series). Supports \"padding\" for intervals without activity."
14
+ s.email = "cary.dunn@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "LICENSE.txt",
23
+ "MIT-LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "has-activity.gemspec",
28
+ "lib/has-activity.rb",
29
+ "lib/has_activity/activitize.rb",
30
+ "lib/has_activity/activitize_calculations.rb",
31
+ "lib/has_activity/core.rb",
32
+ "lib/has_activity/graph_ext.rb",
33
+ "test/helper.rb",
34
+ "test/test_has-activity.rb"
35
+ ]
36
+ s.homepage = "http://github.com/cdunn/has_activity"
37
+ s.licenses = ["MIT"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = "1.8.11"
40
+ s.summary = "A simple way to grab recent activity on a given model grouped by hour, day, week or month (time series)."
41
+
42
+ if s.respond_to? :specification_version then
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
47
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
48
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
49
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
50
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
51
+ else
52
+ s.add_dependency(%q<shoulda>, [">= 0"])
53
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
54
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
55
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
56
+ s.add_dependency(%q<simplecov>, [">= 0"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<shoulda>, [">= 0"])
60
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
61
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
62
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
63
+ s.add_dependency(%q<simplecov>, [">= 0"])
64
+ end
65
+ end
66
+
@@ -0,0 +1,22 @@
1
+ require "active_record"
2
+ require "active_support"
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+
6
+ module HasActivity
7
+ end
8
+
9
+ require "has_activity/activitize"
10
+ require "has_activity/activitize_calculations"
11
+ require "has_activity/core"
12
+ require "has_activity/graph_ext"
13
+
14
+ $LOAD_PATH.shift
15
+
16
+ if defined?(ActiveRecord::Base)
17
+ ActiveRecord::Base.extend HasActivity::Activitize
18
+ ActiveRecord::Base.send :include, HasActivity::Activitize
19
+
20
+ ActiveRecord::Calculations.extend HasActivity::ActivitizeCalculations
21
+ ActiveRecord::Calculations.send :include, HasActivity::ActivitizeCalculations
22
+ end
@@ -0,0 +1,42 @@
1
+ module HasActivity
2
+ module Activitize
3
+ def activitized?
4
+ false
5
+ end
6
+
7
+ ##
8
+ # Give a model activity methods
9
+ #
10
+ # @param [Hash]
11
+ #
12
+ # Example:
13
+ # class User < ActiveRecord::Base
14
+ # has_activity :on => :created_at
15
+ # end
16
+ def has_activity(options={})
17
+ options[:on] ||= :created_at
18
+ activitize(options)
19
+ end
20
+
21
+ private
22
+
23
+ def activitize(options={})
24
+ if activitized?
25
+ else
26
+ class_attribute :has_activity_options
27
+ self.has_activity_options = options
28
+
29
+ class_eval do
30
+
31
+ def self.activitized?
32
+ true
33
+ end
34
+
35
+ include HasActivity::Core
36
+
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,169 @@
1
+ module HasActivity
2
+ module ActivitizeCalculations
3
+ def self.included(base)
4
+ base.send :include, HasActivity::ActivitizeCalculations::OverallMethods
5
+ base.extend HasActivity::ActivitizeCalculations::OverallMethods
6
+ end
7
+
8
+ module OverallMethods
9
+
10
+ def activity_between(between_start, between_end, options={})
11
+ # Normalize dates...
12
+ start_and_end = [between_start.to_time, between_end.to_time]
13
+ if between_start > between_end
14
+ puts "flip dates..."
15
+ start_and_end = start_and_end.reverse
16
+ end
17
+ calculate_activity(*start_and_end, options.merge(:between => true))
18
+ end
19
+
20
+ def activity_since(since, options={})
21
+ calculate_activity(since.to_time, Time.now, options)
22
+ end
23
+
24
+ private
25
+
26
+ # Grabs a hash of the activity since <time ago> grouped by <hour/day/week>
27
+ #
28
+ # * :padding
29
+ # true/false
30
+ # * :by
31
+ # :hour, :day, :week
32
+ # * :order
33
+ # :asc, :desc
34
+ #
35
+ def calculate_activity(between_start, between_end, options={})
36
+ options[:padding] ||= true
37
+ options[:order] ||= :asc
38
+ options[:by] ||= :hour
39
+ options[:on] ||= has_activity_options[:on]
40
+
41
+ # TODO: check for index on :on column
42
+
43
+ # Verify user ain't gettin cray...
44
+ # TODO: review other possibilities for people to screw up the query...
45
+ raise "You cannot use custom #group filters with #activity_since" if self.group_values.present?
46
+
47
+ if options[:on].is_a?(String)
48
+ # insert raw...
49
+ activity_column = options[:on].split(".").collect { |v|
50
+ connection.quote_column_name(v)
51
+ }.join(".")
52
+ else
53
+ activity_table_name = connection.quote_table_name(self.table.name)
54
+ activity_column_name = connection.quote_column_name(options[:on])
55
+ activity_column = "#{activity_table_name}.#{activity_column_name}"
56
+ end
57
+
58
+ activity_end_time = "'#{between_end.to_s(:db)}'"
59
+
60
+ case options[:by].to_s
61
+ when "hour"
62
+ relation = self.select("
63
+ #{activity_column} AS has_activity_timestamp,
64
+ COUNT(*) AS has_activity_count,
65
+ ((((YEAR(#{activity_end_time}) - YEAR(#{activity_column}))*365)+(DAYOFYEAR(#{activity_end_time})-DAYOFYEAR(#{activity_column})))*24)+(HOUR(#{activity_end_time})-HOUR(#{activity_column})) AS has_activity_hours_ago,
66
+ CONCAT(YEAR(#{activity_column}), CONCAT(DAYOFYEAR(#{activity_column}), HOUR(#{activity_column}))) AS has_activity_uniqueness
67
+ ")
68
+ unit = "hours"
69
+ oldest_possible_unit = ((between_end-between_start)/60)/60
70
+ when "day"
71
+ relation = self.select("
72
+ #{activity_column} AS has_activity_timestamp,
73
+ COUNT(*) AS has_activity_count,
74
+ DATEDIFF(#{activity_end_time}, #{activity_column}) AS has_activity_days_ago,
75
+ CONCAT(YEAR(#{activity_column}), CONCAT(DAYOFYEAR(#{activity_column}))) AS has_activity_uniqueness
76
+ ")
77
+ unit = "days"
78
+ oldest_possible_unit = (((between_end-between_start)/60)/60)/24
79
+ when "week"
80
+ relation = self.select("
81
+ #{activity_column} AS has_activity_timestamp,
82
+ COUNT(*) AS has_activity_count,
83
+ ((YEAR(#{activity_end_time}) - YEAR(#{activity_column}))*52)+(WEEK(#{activity_end_time})-WEEK(#{activity_column})) AS has_activity_weeks_ago,
84
+ YEARWEEK(#{activity_column}) AS has_activity_uniqueness
85
+ ")
86
+ unit = "weeks"
87
+ oldest_possible_unit = ((((between_end-between_start)/60)/60)/24)/7
88
+ when "month"
89
+ relation = self.select("
90
+ #{activity_column} AS has_activity_timestamp,
91
+ COUNT(*) AS has_activity_count,
92
+ ((YEAR(#{activity_end_time}) - YEAR(#{activity_column}))*12)+(MONTH(#{activity_end_time})-MONTH(#{activity_column})) AS has_activity_months_ago,
93
+ CONCAT(YEAR(#{activity_column}), CONCAT(MONTH(#{activity_column}))) AS has_activity_uniqueness
94
+ ")
95
+ unit = "months"
96
+ oldest_possible_unit = (between_end.year*12+between_end.month) - (between_start.year*12+between_start.month)
97
+ else
98
+ raise "Invalid option :by (:hour, :day, :week, :month)"
99
+ end
100
+
101
+ if options[:between]
102
+ relation = relation.where("#{activity_column} BETWEEN ? AND ?", between_start, between_end)
103
+ else
104
+ relation = relation.where("#{activity_column} > ?", between_start)
105
+ end
106
+ relation = relation.group("has_activity_uniqueness").order("#{activity_column} ASC")
107
+ results = connection.select_all(relation.to_sql)
108
+
109
+ (options[:padding] ? pad_activity_results(results, between_end, unit, oldest_possible_unit.round, options[:order]) : format_activity_results(results, unit, order))
110
+ end
111
+
112
+ def format_activity_results(results, unit, order)
113
+ results.inject([]) do |rs,r|
114
+ entry = {
115
+ :offset => r["has_activity_#{unit}_ago"].to_i,
116
+ :activity => r["has_activity_count"].to_i,
117
+ :date => round_activity_timestamp(r["has_activity_timestamp"].is_a?(String) ? Time.parse(r["has_activity_timestamp"]) : r["has_activity_timestamp"], unit).in_time_zone
118
+ }
119
+ (order.to_s == "asc") ? rs.push(entry) : rs.unshift(entry)
120
+ end
121
+ end
122
+
123
+ def pad_activity_results(results, between_end, unit, oldest_possible_offset, order)
124
+ padded_results = []
125
+
126
+ current_unit_offset = oldest_possible_offset
127
+ current_result_index = 0
128
+
129
+ while current_unit_offset >= 0 do
130
+ if current_result_index < results.size && results[current_result_index]["has_activity_#{unit}_ago"].to_i == current_unit_offset
131
+ entry = {
132
+ :offset => current_unit_offset,
133
+ :activity => results[current_result_index]["has_activity_count"].to_i,
134
+ :timestamp => round_activity_timestamp(results[current_result_index]["has_activity_timestamp"].is_a?(String) ? Time.parse(results[current_result_index]["has_activity_timestamp"]) : results[current_result_index]["has_activity_timestamp"], unit).in_time_zone
135
+ }
136
+ current_result_index = current_result_index+1
137
+ else
138
+ case unit
139
+ when "hours"
140
+ created_at_given_offset = between_end-current_unit_offset.hours
141
+ when "days"
142
+ created_at_given_offset = between_end-current_unit_offset.days
143
+ when "weeks"
144
+ created_at_given_offset = between_end-current_unit_offset.weeks
145
+ when "months"
146
+ created_at_given_offset = between_end-current_unit_offset.months
147
+ else
148
+ raise "Invalid unit"
149
+ end
150
+ entry = {
151
+ :offset => current_unit_offset,
152
+ :activity => 0,
153
+ :timestamp => round_activity_timestamp(created_at_given_offset, unit)
154
+ }
155
+ end
156
+ current_unit_offset = current_unit_offset-1
157
+ (order.to_s == "asc") ? padded_results.push(entry) : padded_results.unshift(entry)
158
+ end
159
+
160
+ padded_results
161
+ end # pad_activity_results
162
+
163
+ def round_activity_timestamp(timestamp, round_to)
164
+ Time.at((timestamp.to_f / 1.send(round_to)).floor * 1.send(round_to))
165
+ end
166
+
167
+ end # OverallMethods
168
+ end # ActivitizeCalculations
169
+ end # HasActivity
@@ -0,0 +1,20 @@
1
+ module HasActivity
2
+ module Core
3
+ def self.included(base)
4
+ base.send :include, HasActivity::Core::ClassMethods
5
+ base.extend HasActivity::Core::ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def activity_since(*args)
11
+ scoped.activity_since(*args)
12
+ end
13
+
14
+ def activity_between(*args)
15
+ scoped.activity_between(*args)
16
+ end
17
+
18
+ end # ClassMethods
19
+ end # Core
20
+ end # HasActivity
@@ -0,0 +1,34 @@
1
+ unless Array.instance_methods.include? 'to_activity_gchart'
2
+ Array.class_eval do
3
+
4
+ # Returns a URL to a simple google chart the represents the activity returned by the plugin
5
+ #
6
+ # * :type => :bar/:line
7
+ # * :size => "200x50"
8
+ # * :bgcolor => "EFEFEF"
9
+ # * :chart_color => "336699"
10
+ # * :area_color => "DFEBFF" (only for :line)
11
+ # * :line_color => "0077CC" (only for :line)
12
+ # * :line_width => "2" (only for :line)
13
+ #
14
+ def to_activity_gchart(options={})
15
+ options[:type] ||= :bar
16
+ options[:size] ||= "200x50"
17
+ options[:bgcolor] ||= "EFEFEF"
18
+ options[:chart_color] ||= "336699"
19
+ options[:area_color] ||= "DFEBFF"
20
+ options[:line_color] ||= "0077CC"
21
+ options[:line_width] ||= "2"
22
+
23
+ max_data_point = self.max{|a,b| a[:activity] <=> b[:activity] }[:activity]
24
+ activity_str = self.map{|a| a[:activity]}.join(",")
25
+
26
+ if options[:type] == :line
27
+ 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:#{activity_str}&chds=0,#{max_data_point}&chf=bg,s,#{options[:bgcolor]}&"
28
+ else
29
+ return "http://chart.apis.google.com/chart?cht=bvs&chs=#{options[:size]}&chd=t:#{activity_str}&chco=#{options[:chart_color]}&chbh=a,#{options[:line_width]}&chds=0,#{max_data_point}&chf=bg,s,#{options[:bgcolor]}&"
30
+ end
31
+ end
32
+
33
+ end
34
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'has-activity'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestHasActivity < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: has-activity
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Cary Dunn
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: shoulda
16
+ requirement: &70280644148800 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70280644148800
25
+ - !ruby/object:Gem::Dependency
26
+ name: rdoc
27
+ requirement: &70280644148280 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '3.12'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70280644148280
36
+ - !ruby/object:Gem::Dependency
37
+ name: bundler
38
+ requirement: &70280644147640 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70280644147640
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: &70280644147080 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.3
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70280644147080
58
+ - !ruby/object:Gem::Dependency
59
+ name: simplecov
60
+ requirement: &70280644146420 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70280644146420
69
+ description: A simple way to grab recent activity on a given model grouped by hour,
70
+ day, week or month (time series). Supports "padding" for intervals without activity.
71
+ email: cary.dunn@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files:
75
+ - LICENSE.txt
76
+ - README.rdoc
77
+ files:
78
+ - .document
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - MIT-LICENSE
82
+ - README.rdoc
83
+ - Rakefile
84
+ - VERSION
85
+ - has-activity.gemspec
86
+ - lib/has-activity.rb
87
+ - lib/has_activity/activitize.rb
88
+ - lib/has_activity/activitize_calculations.rb
89
+ - lib/has_activity/core.rb
90
+ - lib/has_activity/graph_ext.rb
91
+ - test/helper.rb
92
+ - test/test_has-activity.rb
93
+ homepage: http://github.com/cdunn/has_activity
94
+ licenses:
95
+ - MIT
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ segments:
107
+ - 0
108
+ hash: -4427416923692504441
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.11
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: A simple way to grab recent activity on a given model grouped by hour, day,
121
+ week or month (time series).
122
+ test_files: []