event-counter 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c824074d24fd8d6d102c55c7cd81c4026e3cdd0
4
- data.tar.gz: 906bf98133f1f082d6a3f1c1d4831c64f7974ea3
3
+ metadata.gz: 9ed77b0f7b2996138e3c7125f506022dbfb1b4f6
4
+ data.tar.gz: 703501bc075661a7ef2584740ec9163450a591ed
5
5
  SHA512:
6
- metadata.gz: 8db9c66d38029ccf99b8fa828f5936a1dc8ea84412822d7fc1037b4a2d4979988f429e4b2a96379d23e821b4ad08e792409f617b7ac1eb28f71f429341a608fc
7
- data.tar.gz: a4085a8f4901cd3854b50ff56791c17bcd345d4269845e4ab5523a3bc35c65ced9bd88e6702ac2c0e2c77f8882edc73afdc5a244fa5f8a2bb927866b0f4c1678
6
+ metadata.gz: d71bb461d356f61d8c0afd1718886e0e2be6b507ea1e0994e95b25c2370495921a14167d75a4e702730a8dac9ce5a5daeb2fc759c553e0f9a6265a68fdf2b4a0
7
+ data.tar.gz: aa7d2d7006bee6837fc7fd8440fa11f5e38148e7e478024f1a25f10285cbe3808c5558d0c5e1ab0c7ad8731371545021460293155339851b2e51cb976b759559
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
  /doc/
8
8
  /log
9
9
  /pkg/
10
+ /spec/fixtures/*.sql
10
11
  /spec/reports/
11
12
  /tmp/
12
13
  *.bundle
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
+
7
+ gemfile:
8
+ - gemfiles/pg_ar_30.gemfile
9
+ - gemfiles/pg_ar_31.gemfile
10
+ - gemfiles/pg_ar_32.gemfile
11
+ - gemfiles/pg_ar_40.gemfile
12
+
13
+ script: RUN_ALL=true rspec spec
14
+
15
+ services:
16
+ - postgresql
17
+
18
+ before_script:
19
+ - psql -c 'create database event_counter_test;' -U postgres
data/Appraisals ADDED
@@ -0,0 +1,11 @@
1
+ %w(3.0 3.1 3.2 4.0 4.1).each do |ar_version|
2
+ %w(pg).each do |db_type|
3
+ appraise "#{db_type}-ar-#{ar_version.split('.').first(2).join}" do
4
+ gem 'activerecord', "~> #{ar_version}"
5
+ gem 'activesupport', "~> #{ar_version}"
6
+ gem 'database_cleaner'
7
+ gem 'pg'
8
+ gem 'rspec'
9
+ end
10
+ end
11
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ # EventCounter Changelog
2
+
3
+ 0.1.0 (2014-10-12)
4
+
5
+ * Added time zones support
6
+ * Improved specs
data/Gemfile CHANGED
@@ -1,3 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem 'appraisal'
6
+ gem 'rspec'
7
+ gem 'database_cleaner'
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
- EventCounter
2
- ===============
1
+ # EventCounter
3
2
 
4
3
  EventCounter is a database based event counter with throttling per time intervals.
5
4
 
6
- Usage
7
- -----
5
+ ## Usage
8
6
 
9
7
  Let's define counters in model
10
8
 
@@ -23,66 +21,105 @@ Let's count...
23
21
  article = Article.create!
24
22
 
25
23
  article.up!(:views)
26
- # creates counter (if it doesn't exist) with value 1 and on Time.now() rounded to 5 minutes, e.x.:
27
- #=> #<EventCounter id: 1, name: "views", value: 1, countable_id: 1, countable_type: "Article", created_at: "2014-10-16 23:20:00">
24
+ # => #<EventCounter id: 1, name: "views", value: 1, countable_id: 1,
25
+ # countable_type: "Article", created_at: "2014-10-16 23:20:00">
26
+ # creates counter (if it doesn't exist) with value 1 and on Time.now() rounded
27
+ # to 5 minutes, e.x.:
28
28
 
29
29
  # at once
30
30
  article.up!(:views, 3)
31
- #=> #<EventCounter id: 1, name: "views", value: 4, countable_id: 1, countable_type: "Article", created_at: "2014-10-16 23:20:00">
32
- # it will update counter (if the other exists in that interval) with value 3 and on Time.now() rounded to 5 minutes
31
+ # => #<EventCounter id: 1, name: "views", value: 4, countable_id: 1,
32
+ # countable_type: "Article", created_at: "2014-10-16 23:20:00">
33
+ # Updates counter (if the other exists in that interval) with value 3 and
34
+ # on Time.now() rounded to 5 minutes
33
35
 
34
36
  # later
35
37
  article.up!(:views, 5)
36
- #=> #<EventCounter id: 2, name: "views", value: 5, countable_id: 1, countable_type: "Article", created_at: "2014-10-16 23:25:00">
38
+ # => #<EventCounter id: 2, name: "views", value: 5, countable_id: 1,
39
+ # countable_type: "Article", created_at: "2014-10-16 23:25:00">
37
40
  article.down!(:views, 2)
38
- #=> #<EventCounter id: 2, name: "views", value: 3, countable_id: 1, countable_type: "Article", created_at: "2014-10-16 23:25:00">
41
+ # => #<EventCounter id: 2, name: "views", value: 3, countable_id: 1,
42
+ # countable_type: "Article", created_at: "2014-10-16 23:25:00">
39
43
 
40
44
  # anytime or in a background job
41
- article.up!(:views, 7, on_time: 10.minutes.ago)
42
- #=> #<EventCounter id: 3, name: "views", value: 7, countable_id: 1, countable_type: "Article", created_at: "2014-10-16 23:15:00">
45
+ article.up!(:views, 7, on_time: 10.minutes.ago.in_time_zone)
46
+ # => #<EventCounter id: 3, name: "views", value: 7, countable_id: 1,
47
+ # countable_type: "Article", created_at: "2014-10-16 23:15:00">
43
48
 
44
49
  # we have not got? let's fix it
45
- article.up!(:views, 9, on_time: 10.minutes.ago, force: true)
46
- #=> #<EventCounter id: 3, name: "views", value: 9, countable_id: 1, countable_type: "Article", created_at: "2014-10-16 23:15:00">
50
+ article.up!(:views, 9, on_time: 10.minutes.ago.in_time_zone, force: true)
51
+ # => #<EventCounter id: 3, name: "views", value: 9, countable_id: 1,
52
+ # countable_type: "Article", created_at: "2014-10-16 23:15:00">
47
53
  ```
48
54
 
49
55
  Let's get some statistics for our charts...
50
56
 
51
57
  ```ruby
52
58
  article.data_for(:views)
53
- #=> [[2014-10-16 23:15:00 +0400, 9], [2014-10-16 23:20:00 +0400, 4], [2014-10-16 23:25:00 +0400, 3]]
59
+ # => [
60
+ # [Thu, 16 Oct 2014 23:15:00 MSK +04:00, 9],
61
+ # [Thu, 16 Oct 2014 23:20:00 MSK +04:00, 4],
62
+ # [Thu, 16 Oct 2014 23:25:00 MSK +04:00, 3]
63
+ # ]
54
64
 
55
65
  article.data_for(:views, interval: 10.minutes)
56
- #=> [[2014-10-16 23:10:00 +0400, 9], [2014-10-16 23:20:00 +0400, 7]]
57
-
58
- range = Time.mktime(2014, 10, 16, 23, 0)..Time.mktime(2014, 10, 16, 23, 10)
66
+ # => [
67
+ # [Thu, 16 Oct 2014 23:10:00 MSK +04:00, 9],
68
+ # [Thu, 16 Oct 2014 23:20:00 MSK +04:00, 7]
69
+ # ]
70
+
71
+ # with range
72
+ range_start = Time.mktime(2014, 10, 16, 23, 0).in_time_zone
73
+ range_end = Time.mktime(2014, 10, 16, 23, 10).in_time_zone
74
+ range = range_start..range_end
59
75
  article.data_for(:views, interval: 10.minutes, range: range)
60
- #=> [[2014-10-16 23:00:00 +0400, 0], [2014-10-16 23:10:00 +0400, 9]]
76
+ #=> [
77
+ # [Thu, 16 Oct 2014 23:00:00 MSK +04:00, 0]
78
+ # [Thu, 16 Oct 2014 23:10:00 MSK +04:00, 9]
79
+ # ]
80
+
81
+ # for different time zone (although we have no data for that time)
82
+ range_start = Time.mktime(2014, 10, 16, 23, 0).in_time_zone('UTC')
83
+ range_end = Time.mktime(2014, 10, 16, 23, 10).in_time_zone('UTC')
84
+ range = range_start..range_end
85
+ article.data_for(:views, interval: 10.minutes, range: range, tz: 'UTC')
86
+ #=> [
87
+ # [Thu, 16 Oct 2014 23:00:00 UTC +00:00, 0]
88
+ # [Thu, 16 Oct 2014 23:10:00 UTC +00:00, 0]
89
+ # ]
61
90
 
62
91
  article.data_for(:views, interval: :day)
63
- #=> [[2014-10-16 00:00:00 +0400, 16]]
92
+ # => [Thu, 16 Oct 2014 00:00:00 MSK +04:00, 16]
64
93
 
65
94
  article.data_for(:views, interval: :day, raw: true)
66
- #=> [{"created_at" => "2014-10-16 00:00:00+04", "value" => "16"}]
67
- # raw result will make difference in performance on a big data
95
+ #=> [{"created_at" => "2014-10-16 00:00:00", "value" => "16"}]
96
+ # The raw result will make difference in performance on a big data.
97
+ # The returned time is in the requested time zone. By default, a normalization
98
+ # looks as `Time.zone.parse(i['created_at']), i['value'].to_i ]`
68
99
 
69
100
  # class wide
70
- range = Time.mktime(2014, 10, 15)..Time.mktime(2014, 10, 16)
101
+ range_start = Time.mktime(2014, 10, 15).in_time_zone
102
+ range_end = Time.mktime(2014, 10, 16).in_time_zone
103
+ range = range_start..range_end
71
104
  Article.data_for(:views, interval: :day, range: range)
72
- #=> [[2014-10-15 00:00:00 +0400, 0], [2014-10-16 00:00:00 +0400, 16]]
105
+ # => [
106
+ # [Thu, 15 Oct 2014 00:00:00 MSK +04:00, 0]
107
+ # [Thu, 16 Oct 2014 00:00:00 MSK +04:00, 16]
108
+ # ]
73
109
  ```
74
110
 
75
- Limitations
76
- -----------
111
+ ## Limitations
77
112
 
78
113
  - It works *ONLY* with *PostgreSQL* at the moment.
79
114
  - ActiveRecord 3+
115
+ - ActiveSupport 3+
80
116
  - It's polymorphic association.
117
+ - It uses ActiveSupport::TimeWithZone to return user friendly statistics.
118
+ So, you have to operate with dates with time zones.
81
119
  - Use it in production with caution because it's early release.
82
120
 
83
121
 
84
- Installation
85
- --------------
122
+ ## Installation
86
123
 
87
124
  Add gem to Gemfile
88
125
 
@@ -18,12 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency 'activerecord', '~> 3'
21
+ spec.add_dependency 'activerecord', '>= 3'
22
+ spec.add_dependency 'activesupport', '>= 3'
22
23
  spec.add_dependency 'pg', '~> 0'
23
-
24
- spec.add_development_dependency 'bundler', '~> 1.7'
25
- spec.add_development_dependency 'database_cleaner', '~> 0'
26
- spec.add_development_dependency 'rspec', '~> 3'
27
- spec.add_development_dependency 'fabrication', '~> 0'
28
- spec.add_development_dependency 'rake', '~> 10.0'
29
24
  end
@@ -0,0 +1,12 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rspec"
7
+ gem "database_cleaner"
8
+ gem "activerecord", "~> 3.0"
9
+ gem "activesupport", "~> 3.0"
10
+ gem "pg"
11
+
12
+ gemspec :path => "../"
@@ -0,0 +1,60 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ event-counter (0.1.0)
5
+ activerecord (>= 3)
6
+ activesupport (>= 3)
7
+ pg (~> 0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activemodel (3.2.19)
13
+ activesupport (= 3.2.19)
14
+ builder (~> 3.0.0)
15
+ activerecord (3.2.19)
16
+ activemodel (= 3.2.19)
17
+ activesupport (= 3.2.19)
18
+ arel (~> 3.0.2)
19
+ tzinfo (~> 0.3.29)
20
+ activesupport (3.2.19)
21
+ i18n (~> 0.6, >= 0.6.4)
22
+ multi_json (~> 1.0)
23
+ appraisal (1.0.2)
24
+ bundler
25
+ rake
26
+ thor (>= 0.14.0)
27
+ arel (3.0.3)
28
+ builder (3.0.4)
29
+ database_cleaner (1.3.0)
30
+ diff-lcs (1.2.5)
31
+ i18n (0.6.11)
32
+ multi_json (1.10.1)
33
+ pg (0.17.1)
34
+ rake (10.3.2)
35
+ rspec (3.1.0)
36
+ rspec-core (~> 3.1.0)
37
+ rspec-expectations (~> 3.1.0)
38
+ rspec-mocks (~> 3.1.0)
39
+ rspec-core (3.1.7)
40
+ rspec-support (~> 3.1.0)
41
+ rspec-expectations (3.1.2)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.1.0)
44
+ rspec-mocks (3.1.3)
45
+ rspec-support (~> 3.1.0)
46
+ rspec-support (3.1.2)
47
+ thor (0.19.1)
48
+ tzinfo (0.3.41)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ activerecord (~> 3.0)
55
+ activesupport (~> 3.0)
56
+ appraisal
57
+ database_cleaner
58
+ event-counter!
59
+ pg
60
+ rspec
@@ -0,0 +1,12 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rspec"
7
+ gem "database_cleaner"
8
+ gem "activerecord", "~> 3.1"
9
+ gem "activesupport", "~> 3.1"
10
+ gem "pg"
11
+
12
+ gemspec :path => "../"
@@ -0,0 +1,60 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ event-counter (0.1.0)
5
+ activerecord (>= 3)
6
+ activesupport (>= 3)
7
+ pg (~> 0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activemodel (3.2.19)
13
+ activesupport (= 3.2.19)
14
+ builder (~> 3.0.0)
15
+ activerecord (3.2.19)
16
+ activemodel (= 3.2.19)
17
+ activesupport (= 3.2.19)
18
+ arel (~> 3.0.2)
19
+ tzinfo (~> 0.3.29)
20
+ activesupport (3.2.19)
21
+ i18n (~> 0.6, >= 0.6.4)
22
+ multi_json (~> 1.0)
23
+ appraisal (1.0.2)
24
+ bundler
25
+ rake
26
+ thor (>= 0.14.0)
27
+ arel (3.0.3)
28
+ builder (3.0.4)
29
+ database_cleaner (1.3.0)
30
+ diff-lcs (1.2.5)
31
+ i18n (0.6.11)
32
+ multi_json (1.10.1)
33
+ pg (0.17.1)
34
+ rake (10.3.2)
35
+ rspec (3.1.0)
36
+ rspec-core (~> 3.1.0)
37
+ rspec-expectations (~> 3.1.0)
38
+ rspec-mocks (~> 3.1.0)
39
+ rspec-core (3.1.7)
40
+ rspec-support (~> 3.1.0)
41
+ rspec-expectations (3.1.2)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.1.0)
44
+ rspec-mocks (3.1.3)
45
+ rspec-support (~> 3.1.0)
46
+ rspec-support (3.1.2)
47
+ thor (0.19.1)
48
+ tzinfo (0.3.41)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ activerecord (~> 3.1)
55
+ activesupport (~> 3.1)
56
+ appraisal
57
+ database_cleaner
58
+ event-counter!
59
+ pg
60
+ rspec
@@ -0,0 +1,12 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rspec"
7
+ gem "database_cleaner"
8
+ gem "activerecord", "~> 3.2"
9
+ gem "activesupport", "~> 3.2"
10
+ gem "pg"
11
+
12
+ gemspec :path => "../"
@@ -0,0 +1,60 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ event-counter (0.1.0)
5
+ activerecord (>= 3)
6
+ activesupport (>= 3)
7
+ pg (~> 0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activemodel (3.2.19)
13
+ activesupport (= 3.2.19)
14
+ builder (~> 3.0.0)
15
+ activerecord (3.2.19)
16
+ activemodel (= 3.2.19)
17
+ activesupport (= 3.2.19)
18
+ arel (~> 3.0.2)
19
+ tzinfo (~> 0.3.29)
20
+ activesupport (3.2.19)
21
+ i18n (~> 0.6, >= 0.6.4)
22
+ multi_json (~> 1.0)
23
+ appraisal (1.0.2)
24
+ bundler
25
+ rake
26
+ thor (>= 0.14.0)
27
+ arel (3.0.3)
28
+ builder (3.0.4)
29
+ database_cleaner (1.3.0)
30
+ diff-lcs (1.2.5)
31
+ i18n (0.6.11)
32
+ multi_json (1.10.1)
33
+ pg (0.17.1)
34
+ rake (10.3.2)
35
+ rspec (3.1.0)
36
+ rspec-core (~> 3.1.0)
37
+ rspec-expectations (~> 3.1.0)
38
+ rspec-mocks (~> 3.1.0)
39
+ rspec-core (3.1.7)
40
+ rspec-support (~> 3.1.0)
41
+ rspec-expectations (3.1.2)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.1.0)
44
+ rspec-mocks (3.1.3)
45
+ rspec-support (~> 3.1.0)
46
+ rspec-support (3.1.2)
47
+ thor (0.19.1)
48
+ tzinfo (0.3.41)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ activerecord (~> 3.2)
55
+ activesupport (~> 3.2)
56
+ appraisal
57
+ database_cleaner
58
+ event-counter!
59
+ pg
60
+ rspec