aggtive_record 0.1.2 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YzUxOTY3OTI2MWVmYjg0ZWU0YzVmOTUyMjA0NzhmNGEzMTU5ODhhMg==
4
+ NzM2ZGIxNTQ3MjU2MmI0ZGQ2YmJmOTJjMjQxYjQxZTJmNGYwODI1ZQ==
5
5
  data.tar.gz: !binary |-
6
- YmIzZWJjOGMzMzEzYTc0NzQwZjc0ODQ1YjUyNTVjZWU4ZTFhMmNmZA==
6
+ MmY0YmQ4ZDE1NGNkNTU2ZDZkNjFmNzg2YTczNjIyY2Q4NjIxZGFkNQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ZDBhZGYwOThkN2U5NjQ4NjNiOTA1ZDdkMTA1MTE4YmNmYjI3M2VjZWQxZDg0
10
- NWZkNDE2NDYxNGRiM2QxYjMwMTJmNDIwMDM2MGFhYTAzNDBhM2Y5MGFmMjQw
11
- MzI3NGRiYjkzZjMwNWU5NjdiYzhkMjA4OTA5YjBkMmZhNzExYzg=
9
+ MGZkMWFhMTFiMGMzODllNmY0ZDI5MmNmYWM4Zjg0NDA4MjRkZjQ4YmNhNzFm
10
+ MmQ1ODRlMWVlMjg1ZDY0MmJjNDZmOTBiMDRmMjNmMzBiZDYxOTc4NjFlNWM0
11
+ M2JhMWM3NDJhN2IxMWNkOWU5ZTNmMTJlYTg2MjU0YWFiMTZjYzg=
12
12
  data.tar.gz: !binary |-
13
- ZWQyMjNiMzE3Y2ZlYzZiYmE5MWJkYjdhOWQ1NGM3ODY4YzhmYmUyZDJhNWJl
14
- MTg4MWUxOWRlZThkNTYyMWM5ZWUyNWZkN2QwN2MyNzQwNmRjNDhjYzM1ZDc0
15
- NzdhMGU3OWVhNGVmMDRhZjNmMDkyY2Q4Yzk4NTVjODlkYzc1ZjY=
13
+ MGQyOWZhNWMzMjgwMjVmNGM1N2RkMGJhZDA0NjI1MWEyZjNiNzk4YjJiNTNm
14
+ ZjRiMzNjNjlhZmYyMWUzODcwNTA3OWYwNzRhNzhlZWQ1NzhlMTZhMzE3Y2I1
15
+ MmI5Mzk2NWI0MzM2NGJkZmJhNGYyODkyOTNmNDAwNTlkODNjMjU=
data/Gemfile CHANGED
@@ -9,6 +9,7 @@ group :development do
9
9
  gem 'database_cleaner', '~> 1.0.1'
10
10
  gem 'mysql2'
11
11
  gem 'activerecord', '~> 3.2.14'
12
+ gem 'timecop'
12
13
  end
13
14
 
14
15
  gem 'groupdate'
data/Gemfile.lock CHANGED
@@ -76,6 +76,7 @@ GEM
76
76
  diff-lcs (>= 1.1.3, < 2.0)
77
77
  rspec-mocks (2.14.3)
78
78
  slop (3.4.6)
79
+ timecop (0.6.3)
79
80
  tzinfo (0.3.37)
80
81
 
81
82
  PLATFORMS
@@ -91,3 +92,4 @@ DEPENDENCIES
91
92
  mysql2
92
93
  pry
93
94
  rspec (~> 2.14.1)
95
+ timecop
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.5
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "aggtive_record"
8
- s.version = "0.1.2"
8
+ s.version = "0.1.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Dan Nguyen"]
12
- s.date = "2013-09-23"
12
+ s.date = "2013-10-02"
13
13
  s.description = "This is not even remotely finished or even started on. Please don't download."
14
14
  s.email = "dansonguyen@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -35,12 +35,13 @@ Gem::Specification.new do |s|
35
35
  "lib/aggtive_record/egg_scopes.rb",
36
36
  "lib/aggtive_record/egg_scopes/collation.rb",
37
37
  "lib/aggtive_record/egg_scopes/collation/count_by.rb",
38
- "lib/aggtive_record/egg_scopes/collation/rate.rb",
38
+ "lib/aggtive_record/egg_scopes/collation/rate_per.rb",
39
39
  "lib/aggtive_record/egg_scopes/time_bucket.rb",
40
40
  "lib/aggtive_record/egg_scopes/time_span.rb",
41
41
  "lib/aggtive_record/memo.rb",
42
42
  "lib/aggtive_record/time.rb",
43
43
  "spec/functional/basic_object_run_spec.rb",
44
+ "spec/functional/collation_spec.rb",
44
45
  "spec/lib/aggable_spec.rb",
45
46
  "spec/lib/count_by_spec.rb",
46
47
  "spec/lib/rate_spec.rb",
@@ -67,6 +68,7 @@ Gem::Specification.new do |s|
67
68
  s.add_development_dependency(%q<database_cleaner>, ["~> 1.0.1"])
68
69
  s.add_development_dependency(%q<mysql2>, [">= 0"])
69
70
  s.add_development_dependency(%q<activerecord>, ["~> 3.2.14"])
71
+ s.add_development_dependency(%q<timecop>, [">= 0"])
70
72
  else
71
73
  s.add_dependency(%q<groupdate>, [">= 0"])
72
74
  s.add_dependency(%q<activesupport>, ["~> 3.2.14"])
@@ -77,6 +79,7 @@ Gem::Specification.new do |s|
77
79
  s.add_dependency(%q<database_cleaner>, ["~> 1.0.1"])
78
80
  s.add_dependency(%q<mysql2>, [">= 0"])
79
81
  s.add_dependency(%q<activerecord>, ["~> 3.2.14"])
82
+ s.add_dependency(%q<timecop>, [">= 0"])
80
83
  end
81
84
  else
82
85
  s.add_dependency(%q<groupdate>, [">= 0"])
@@ -88,6 +91,7 @@ Gem::Specification.new do |s|
88
91
  s.add_dependency(%q<database_cleaner>, ["~> 1.0.1"])
89
92
  s.add_dependency(%q<mysql2>, [">= 0"])
90
93
  s.add_dependency(%q<activerecord>, ["~> 3.2.14"])
94
+ s.add_dependency(%q<timecop>, [">= 0"])
91
95
  end
92
96
  end
93
97
 
@@ -12,8 +12,19 @@ module AggtiveRecord
12
12
  span_foo = "by_#{time_period}"
13
13
  self.send(span_foo).count
14
14
  end
15
+
16
+ # define dynamically
17
+ AggtiveRecord::Time.periods.each do |period_name|
18
+ foo_name = "count_by_#{period_name}".to_sym
19
+ # defining scope here, dynamically
20
+ define_method foo_name do
21
+ self.count_by(period_name)
22
+ end
23
+ end
15
24
  end
16
25
 
26
+
27
+
17
28
  end
18
29
  end
19
30
  end
@@ -0,0 +1,76 @@
1
+ module AggtiveRecord
2
+ module EggScopes
3
+ module Collation
4
+ module Rate
5
+ extend ActiveSupport::Concern
6
+
7
+ # Public: a rate
8
+ # expects that ActiveRelation has a grouping
9
+ # self is a ActiveRecord scope
10
+
11
+ module ClassMethods
12
+
13
+ # Public
14
+ #
15
+ # Returns float indicating rate of records per given time period
16
+ def rate_per(time_period, timespan_in_seconds = nil)
17
+ # tk: this may be unnecessary
18
+ records = self.scoped.to_a
19
+
20
+ time_period_secs = AggtiveRecord::Time.to_seconds(time_period)
21
+ timespan_in_seconds ||= self.timespan_to_now(records)
22
+
23
+
24
+
25
+ return records.size.to_f * time_period_secs / timespan_in_seconds
26
+ end
27
+
28
+ # defines rate_per_year, rate_per_hour
29
+ # except that rate_per_year also accepts an optional argument
30
+
31
+ AggtiveRecord::Time.periods.each do |period_name|
32
+ foo_name = "rate_per_#{period_name}".to_sym
33
+ # defining scope here, dynamically
34
+ define_method foo_name do |*args|
35
+
36
+
37
+ if args[0].present?
38
+ # i.e: #rate_per_month(:past_year)
39
+ past_scope = args[0] # past_year
40
+ raise ArgumentError, "Must be a scope with 'past_'" unless past_scope.to_s =~ /^past_/
41
+
42
+ time_scoped_records = self.send( past_scope )
43
+ past_time_span_name = past_scope.to_s.match(/past_(\w+)/)[1]
44
+ past_period_in_seconds = AggtiveRecord::Time.to_seconds(past_time_span_name)
45
+ else
46
+ time_scoped_records = scoped
47
+ past_period_in_seconds = self.timespan_to_now(time_scoped_records)
48
+ end
49
+
50
+ # puts "Past #{past_time_span_name} in seconds: #{past_period_in_seconds}"
51
+ time_scoped_records.send( :rate_per, period_name, past_period_in_seconds )
52
+ end
53
+ end
54
+ end
55
+
56
+
57
+ # included do
58
+
59
+ # # singular time periods
60
+ # # e.g. scope :past_year, ->{ past_time_periods(1, :year)}
61
+
62
+
63
+ # end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ =begin
71
+
72
+ Record.rate_per :hour
73
+ .rate_per :day
74
+
75
+
76
+ =end
@@ -1,5 +1,5 @@
1
1
  require_relative 'collation/count_by'
2
- require_relative 'collation/rate'
2
+ require_relative 'collation/rate_per'
3
3
 
4
4
  module AggtiveRecord
5
5
  module EggScopes
@@ -21,8 +21,12 @@ module AggtiveRecord
21
21
  SECONDS_PER_DAY = 60 * 60 * 24
22
22
 
23
23
  # probably reinventing the wheel here...
24
- def self.to_seconds(sym)
25
- case sym.to_sym
24
+ def self.to_seconds(str)
25
+
26
+ num, period = str.to_s.match(/^(\d*)_?(\w+?)s?$/)[1..2]
27
+ num = num.to_i > 0 ? num.to_i : 1 # ugh
28
+
29
+ secs = case period.to_sym
26
30
  when :year
27
31
  SECONDS_PER_DAY * 365
28
32
  when :month
@@ -38,6 +42,8 @@ module AggtiveRecord
38
42
  when :second
39
43
  1
40
44
  end
45
+
46
+ num * secs
41
47
  end
42
48
 
43
49
 
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe AggtiveRecord do
5
+
6
+
7
+ context 'collation methods acting in concert' do
8
+ before(:each) do
9
+ Timecop.freeze(Time.parse '2013-10-02')
10
+ MusicRecord.create(published_at: 5.days.ago)
11
+ MusicRecord.create(published_at: 1.month.ago)
12
+ MusicRecord.create(published_at: 9.months.ago)
13
+ MusicRecord.create(published_at: 14.months.ago)
14
+ end
15
+
16
+
17
+ it '#past_14_days' do
18
+ expect(MusicRecord.past_14_days.count).to eq 1
19
+ end
20
+
21
+ it '#rate_per_week(:past_14_days)' do
22
+ expect(MusicRecord.rate_per_week(:past_14_days)).to eq 0.5
23
+ end
24
+
25
+ it '#past_year' do
26
+ expect(MusicRecord.past_year.count).to eq 3
27
+ end
28
+
29
+
30
+ it '#past_year.count_by_year' do
31
+ expect(MusicRecord.past_year.count_by_year).to eq( {Time.new(Time.now.year) => 3})
32
+ end
33
+
34
+
35
+ it '#past_year.count_by_week' do
36
+ expect(MusicRecord.past_year.count_by_week).to eq(
37
+ { Time.parse( "2012-12-30 00:00:00 -0500") =>1,
38
+ Time.parse( "2013-09-01 00:00:00 -0400") =>1,
39
+ Time.parse( "2013-09-22 00:00:00 -0400") =>1
40
+ }
41
+ )
42
+ end
43
+
44
+ end
45
+ end
@@ -3,47 +3,34 @@ require 'spec_helper'
3
3
  describe "AggtiveRecord::EggScopes -- .rate" do
4
4
 
5
5
 
6
- describe '#rate_for' do
6
+ describe '#rate_per' do
7
7
  context 'singular periods' do
8
8
  it 'should get about 1 a year' do
9
9
  @record = MusicRecord.create published_at: 12.months.ago
10
10
  expect(MusicRecord.scoped.rate_per(:year) ).to be_within(0.1).of 1
11
11
  end
12
- end
13
-
14
- context 'has two optional parameters' do
15
-
16
- before(:each) do
17
- MusicRecord.create(published_at: 1.day.ago )
18
- end
12
+
19
13
 
20
- let(:records){ MusicRecord.scoped }
21
-
22
- context 'first parameter is the :start_time' do
23
- it 'bounds range with :start_time and Time.now' do
24
- pending 'rethink'
25
- expect(records.rate_per(:day, 2.days.ago)).to be_within(0.1).of 0.5
14
+ context 'meta methods' do
15
+ it 'should have #rate_per_month' do
16
+ MusicRecord.create published_at: (1.month.ago - 1.second)
17
+ MusicRecord.create published_at: 12.days.ago
18
+ expect(MusicRecord.rate_per_month ).to be_within(0.01).of 2
26
19
  end
27
- end
28
20
 
29
- context 'second parameter is the end_time' do
30
- it 'bounds range with :start_time and :end_time' do
31
- pending 'rethink'
32
- expect(records.rate_per(:day, 2.days.ago)).to be_within(0.1).of 0.5
21
+ it 'should have #rate_per_hour' do
22
+ MusicRecord.create published_at: (59.minutes.ago)
23
+ MusicRecord.create published_at: 59.minutes.ago
24
+ expect(MusicRecord.rate_per_hour ).to be_within(0.1).of 2
33
25
  end
34
26
 
35
- it 'has no effect on :where' do
36
- pending('This is troublesome. What if a user calls:
37
- records.past_year.rate_per(:day, 10.days.ago, 3.days.ago)
38
- -- too many surprises here!
39
- ')
40
- end
41
27
  end
42
28
 
43
-
29
+
44
30
  it 'should raise an error when a non-time period is passed in'
45
- it 'should play nicely with other methods'
31
+
46
32
  end
33
+
47
34
  end
48
35
 
49
36
  describe '#timespan_of' do
@@ -64,6 +51,36 @@ describe "AggtiveRecord::EggScopes -- .rate" do
64
51
 
65
52
  it 'should get #latest record in a set without re-querying database'
66
53
  end
54
+ end
55
+
56
+
57
+ # This is not usable
58
+ #
59
+ # context 'has two optional parameters' do
60
+
61
+ # before(:each) do
62
+ # MusicRecord.create(published_at: 1.day.ago )
63
+ # end
64
+
65
+ # let(:records){ MusicRecord.scoped }
66
+
67
+ # context 'first parameter is the :start_time' do
68
+ # it 'bounds range with :start_time and Time.now' do
69
+ # pending 'rethink'
70
+ # expect(records.rate_per(:day, 2.days.ago)).to be_within(0.1).of 0.5
71
+ # end
72
+ # end
67
73
 
74
+ # context 'second parameter is the end_time' do
75
+ # it 'bounds range with :start_time and :end_time' do
76
+ # pending 'rethink'
77
+ # expect(records.rate_per(:day, 2.days.ago)).to be_within(0.1).of 0.5
78
+ # end
68
79
 
69
- end
80
+ # it 'has no effect on :where' do
81
+ # pending('This is troublesome. What if a user calls:
82
+ # records.past_year.rate_per(:day, 10.days.ago, 3.days.ago)
83
+ # -- too many surprises here!
84
+ # ')
85
+ # end
86
+ # end
data/spec/spec_helper.rb CHANGED
@@ -9,6 +9,8 @@ require 'database_cleaner'
9
9
  require 'aggtive_record'
10
10
  require 'pry'
11
11
 
12
+ require 'timecop'
13
+
12
14
  # Requires supporting files with custom matchers and macros, etc,
13
15
  # in ./support/ and its subdirectories.
14
16
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aggtive_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Nguyen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-23 00:00:00.000000000 Z
11
+ date: 2013-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: groupdate
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ~>
137
137
  - !ruby/object:Gem::Version
138
138
  version: 3.2.14
139
+ - !ruby/object:Gem::Dependency
140
+ name: timecop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description: This is not even remotely finished or even started on. Please don't download.
140
154
  email: dansonguyen@gmail.com
141
155
  executables: []
@@ -162,12 +176,13 @@ files:
162
176
  - lib/aggtive_record/egg_scopes.rb
163
177
  - lib/aggtive_record/egg_scopes/collation.rb
164
178
  - lib/aggtive_record/egg_scopes/collation/count_by.rb
165
- - lib/aggtive_record/egg_scopes/collation/rate.rb
179
+ - lib/aggtive_record/egg_scopes/collation/rate_per.rb
166
180
  - lib/aggtive_record/egg_scopes/time_bucket.rb
167
181
  - lib/aggtive_record/egg_scopes/time_span.rb
168
182
  - lib/aggtive_record/memo.rb
169
183
  - lib/aggtive_record/time.rb
170
184
  - spec/functional/basic_object_run_spec.rb
185
+ - spec/functional/collation_spec.rb
171
186
  - spec/lib/aggable_spec.rb
172
187
  - spec/lib/count_by_spec.rb
173
188
  - spec/lib/rate_spec.rb
@@ -1,35 +0,0 @@
1
- module AggtiveRecord
2
- module EggScopes
3
- module Collation
4
- module Rate
5
- extend ActiveSupport::Concern
6
-
7
- # Public: a rate
8
- # expects that ActiveRelation has a grouping
9
- # self is a ActiveRecord scope
10
-
11
- module ClassMethods
12
-
13
- # Public
14
- #
15
- # Returns float indicating rate of records per given time period
16
- def rate_per(time_period)
17
- time_period_secs = AggtiveRecord::Time.to_seconds(time_period)
18
- records = self.scoped.to_a
19
-
20
- return records.size.to_f * time_period_secs / self.timespan_to_now(records)
21
- end
22
- end
23
-
24
- end
25
- end
26
- end
27
- end
28
-
29
- =begin
30
-
31
- Record.rate_per :hour
32
- .rate_per :day
33
-
34
-
35
- =end