chronological 0.0.9 → 1.0.0beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ postgres_connection_options = {
2
+ :adapter => 'postgresql',
3
+ :host => 'localhost',
4
+ :database => 'chronological',
5
+ :username => ENV['USER'],
6
+ :min_messages => 'warning',
7
+ :encoding => 'utf8' }
8
+
9
+ ActiveRecord::Base.establish_connection postgres_connection_options.merge(
10
+ :database => 'postgres',
11
+ :schema_search_path => 'public')
12
+
13
+ ActiveRecord::Base.connection.drop_database postgres_connection_options[:database] rescue nil
14
+ ActiveRecord::Base.connection.create_database postgres_connection_options[:database]
15
+
16
+ ActiveRecord::Base.establish_connection postgres_connection_options
17
+
18
+ ActiveRecord::Base.connection.create_table :base_chronologicables do |t|
19
+ t.datetime :started_at
20
+ t.datetime :ended_at
21
+ end
22
+
23
+ ActiveRecord::Base.connection.create_table :relative_chronologicables do |t|
24
+ t.integer :starting_offset
25
+ t.integer :ending_offset
26
+ t.datetime :base_datetime_utc
27
+ end
28
+
29
+ ActiveRecord::Base.connection.create_table :absolute_chronologicables do |t|
30
+ t.datetime :started_at_utc
31
+ t.datetime :ended_at_utc
32
+ end
33
+
34
+ ActiveRecord::Base.connection.create_table :chronologicable_with_time_zones do |t|
35
+ t.datetime :started_at_utc
36
+ t.datetime :ended_at_utc
37
+ t.string :time_zone
38
+ end
39
+
40
+ RSpec.configure do |config|
41
+ config.before(:each) do
42
+ ActiveRecord::Base.connection.execute 'DELETE FROM base_chronologicables'
43
+ ActiveRecord::Base.connection.execute 'DELETE FROM relative_chronologicables'
44
+ ActiveRecord::Base.connection.execute 'DELETE FROM absolute_chronologicables'
45
+ ActiveRecord::Base.connection.execute 'DELETE FROM chronologicable_with_time_zones'
46
+ end
47
+ end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chronological
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
5
- prerelease:
4
+ version: 1.0.0beta1
5
+ prerelease: 5
6
6
  platform: ruby
7
7
  authors:
8
8
  - jfelchner
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-10-26 00:00:00.000000000 Z
13
+ date: 2012-10-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -125,13 +125,13 @@ dependencies:
125
125
  - !ruby/object:Gem::Version
126
126
  version: 3.1.8
127
127
  - !ruby/object:Gem::Dependency
128
- name: sqlite3
128
+ name: pg
129
129
  requirement: !ruby/object:Gem::Requirement
130
130
  none: false
131
131
  requirements:
132
132
  - - ~>
133
133
  - !ruby/object:Gem::Version
134
- version: 1.3.6
134
+ version: 0.14.1
135
135
  type: :development
136
136
  prerelease: false
137
137
  version_requirements: !ruby/object:Gem::Requirement
@@ -139,7 +139,7 @@ dependencies:
139
139
  requirements:
140
140
  - - ~>
141
141
  - !ruby/object:Gem::Version
142
- version: 1.3.6
142
+ version: 0.14.1
143
143
  - !ruby/object:Gem::Dependency
144
144
  name: timecop
145
145
  requirement: !ruby/object:Gem::Requirement
@@ -164,18 +164,24 @@ extra_rdoc_files:
164
164
  - README.md
165
165
  - LICENSE
166
166
  files:
167
- - lib/chronological/absolute_timeframe.rb
168
- - lib/chronological/base.rb
169
- - lib/chronological/relative_timeframe.rb
167
+ - lib/chronological/errors.rb
168
+ - lib/chronological/strategies/absolute.rb
169
+ - lib/chronological/strategies/base.rb
170
+ - lib/chronological/strategies/relative.rb
171
+ - lib/chronological/strategies.rb
172
+ - lib/chronological/strategy_resolver.rb
170
173
  - lib/chronological/version.rb
171
174
  - lib/chronological.rb
172
175
  - Rakefile
173
176
  - README.md
174
177
  - LICENSE
175
- - spec/absolute_timeframe_spec.rb
176
- - spec/base_spec.rb
177
- - spec/relative_timeframe_spec.rb
178
+ - spec/chronological_spec.rb
178
179
  - spec/spec_helper.rb
180
+ - spec/strategies/absolute_spec.rb
181
+ - spec/strategies/base_spec.rb
182
+ - spec/strategies/relative_spec.rb
183
+ - spec/strategy_resolver_spec.rb
184
+ - spec/support/active_record.rb
179
185
  - spec/support/focused.rb
180
186
  - spec/support/pending.rb
181
187
  - spec/support/timecop.rb
@@ -195,9 +201,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
195
201
  required_rubygems_version: !ruby/object:Gem::Requirement
196
202
  none: false
197
203
  requirements:
198
- - - ! '>='
204
+ - - ! '>'
199
205
  - !ruby/object:Gem::Version
200
- version: '0'
206
+ version: 1.3.1
201
207
  requirements: []
202
208
  rubyforge_project: chronological
203
209
  rubygems_version: 1.8.24
@@ -205,10 +211,13 @@ signing_key:
205
211
  specification_version: 3
206
212
  summary: Easy Accessors for ActiveModel Objects
207
213
  test_files:
208
- - spec/absolute_timeframe_spec.rb
209
- - spec/base_spec.rb
210
- - spec/relative_timeframe_spec.rb
214
+ - spec/chronological_spec.rb
211
215
  - spec/spec_helper.rb
216
+ - spec/strategies/absolute_spec.rb
217
+ - spec/strategies/base_spec.rb
218
+ - spec/strategies/relative_spec.rb
219
+ - spec/strategy_resolver_spec.rb
220
+ - spec/support/active_record.rb
212
221
  - spec/support/focused.rb
213
222
  - spec/support/pending.rb
214
223
  - spec/support/timecop.rb
@@ -1,98 +0,0 @@
1
- module Chronological
2
- module AbsoluteTimeframe
3
- module ClassMethods
4
- # TODO: Needs to be able to add a validation option which can do the
5
- # typical timeliness validation such as ended_at should be after started_at
6
- # and that both should validate timeliness
7
- def absolute_timeframe(options = {})
8
- start_time_field = options[:start_utc] || options[:start]
9
- start_date_field = start_time_field.to_s.gsub(/_at/, '_on')
10
- end_time_field = options[:end_utc] || options[:end]
11
- end_date_field = end_time_field.to_s.gsub(/_at/, '_on')
12
- time_zone = options[:time_zone]
13
- start_time_field_is_utc = options.has_key? :start_utc
14
- end_time_field_is_utc = options.has_key? :end_utc
15
- start_time_field_utc_suffix = start_time_field_is_utc ? '_utc' : ''
16
- end_time_field_utc_suffix = end_time_field_is_utc ? '_utc' : ''
17
-
18
- define_method(:scheduled?) do
19
- optional_time_zone = !options[:time_zone].nil? ? send(time_zone) : true
20
-
21
- send(start_time_field).present? && send(end_time_field).present? && optional_time_zone
22
- end
23
-
24
- define_method(:partially_scheduled?) do
25
- optional_time_zone = !options[:time_zone].nil? ? send(time_zone) : false
26
-
27
- send(start_time_field).present? || send(end_time_field).present? || optional_time_zone
28
- end
29
-
30
- ###
31
- # Scopes
32
- #
33
- self.class.send(:define_method, :by_date) do
34
- order "#{table_name}.#{start_time_field} ASC, #{table_name}.#{end_time_field} ASC"
35
- end
36
-
37
- self.class.send(:define_method, :by_date_reversed) do
38
- order "#{table_name}.#{start_time_field} DESC, #{table_name}.#{end_time_field} DESC"
39
- end
40
-
41
- self.class.send(:define_method, :expired) do
42
- where("#{end_time_field} <= :now", :now => Time.now.utc)
43
- end
44
-
45
- self.class.send(:define_method, :current) do
46
- where("#{end_time_field} > :now", :now => Time.now.utc)
47
- end
48
-
49
- self.class.send(:define_method, :in_progress) do
50
- where("#{start_time_field} <= :now AND #{end_time_field} > :now", :now => Time.now.utc)
51
- end
52
-
53
- self.class.send(:define_method, :started) do
54
- where("#{start_time_field} <= :now", :now => Time.now.utc)
55
- end
56
-
57
- self.class.send(:define_method, :in_progress?) do
58
- in_progress.any?
59
- end
60
-
61
- ###
62
- # Aliases
63
- #
64
- # Aliasing date methods to make code more readable
65
- instance_eval do
66
- alias active? in_progress?
67
- alias active in_progress
68
- end
69
-
70
- class_eval do
71
- alias_attribute :"starts_at#{start_time_field_utc_suffix}", start_time_field.to_sym
72
- alias_attribute :"starting_at#{start_time_field_utc_suffix}", start_time_field.to_sym
73
- alias_attribute :"ends_at#{start_time_field_utc_suffix}", end_time_field.to_sym
74
- alias_attribute :"ending_at#{start_time_field_utc_suffix}", end_time_field.to_sym
75
- end
76
-
77
- base_timeframe start_date_field: start_date_field,
78
- start_time_field: start_time_field,
79
- end_date_field: end_date_field,
80
- end_time_field: end_time_field
81
-
82
- private
83
- define_method(:has_absolute_timeframe?) do
84
- send(start_time_field).present? && send(end_time_field).present?
85
- end
86
-
87
- define_method(:duration_in_seconds) do
88
- (send(end_time_field) - send(start_time_field))
89
- end
90
- end
91
- end
92
-
93
- def self.included(base)
94
- base.extend Chronological::Base
95
- base.extend ClassMethods
96
- end
97
- end
98
- end
@@ -1,41 +0,0 @@
1
- module Chronological
2
- module Base
3
- def base_timeframe(options = {})
4
- define_method(options[:start_date_field]) do
5
- return nil unless send(options[:start_time_field]).respond_to? :to_date
6
-
7
- send(options[:start_time_field]).to_date
8
- end
9
-
10
- define_method(options[:end_date_field]) do
11
- return nil unless send(options[:end_time_field]).respond_to? :to_date
12
-
13
- send(options[:end_time_field]).to_date
14
- end
15
-
16
- define_method(:inactive?) do
17
- !active?
18
- end
19
-
20
- define_method(:duration) do
21
- return Hash.new unless duration_in_seconds.present?
22
-
23
- hours = (duration_in_seconds / 3600).to_i
24
- minutes = ((duration_in_seconds % 3600) / 60).to_i
25
- seconds = (duration_in_seconds % 60).to_i
26
-
27
- { :hours => hours, :minutes => minutes, :seconds => seconds }
28
- end
29
-
30
- define_method(:in_progress?) do
31
- return false unless has_absolute_timeframe?
32
-
33
- (send(options[:start_time_field]) <= Time.now.utc) && send(options[:end_time_field]).future?
34
- end
35
-
36
- class_eval do
37
- alias active? in_progress?
38
- end
39
- end
40
- end
41
- end
@@ -1,96 +0,0 @@
1
- module Chronological
2
- module RelativeTimeframe
3
- module ClassMethods
4
- def relative_timeframe(options = {})
5
- base_time_field = options[:base_utc] || options[:base]
6
- base_time_field_is_utc = options.has_key? :base_utc
7
- time_field_utc_suffix = base_time_field_is_utc ? 'utc' : nil
8
-
9
- start_time_field = ['started_at', time_field_utc_suffix].compact.join('_')
10
- end_time_field = ['ended_at', time_field_utc_suffix].compact.join('_')
11
- start_date_field = ['started_on', time_field_utc_suffix].compact.join('_')
12
- end_date_field = ['ended_on', time_field_utc_suffix].compact.join('_')
13
-
14
- class_eval do
15
- columns_hash[start_time_field] = ActiveRecord::ConnectionAdapters::Column.new(start_time_field, nil, "datetime")
16
- columns_hash[end_time_field] = ActiveRecord::ConnectionAdapters::Column.new(end_time_field, nil, "datetime")
17
- end
18
-
19
- unless base_time_field_is_utc
20
- define_method("#{start_time_field}_utc") do
21
- return nil unless send(start_time_field).present?
22
-
23
- send(start_time_field).in_time_zone('UTC')
24
- end
25
-
26
- define_method("#{end_time_field}_utc") do
27
- return nil unless send(end_time_field).present?
28
-
29
- send(end_time_field).in_time_zone('UTC')
30
- end
31
- end
32
-
33
- define_method(start_time_field) do
34
- return nil unless send(base_time_field).present? && send(options[:start]).present?
35
-
36
- send(base_time_field) - send(options[:start])
37
- end
38
-
39
- define_method(end_time_field) do
40
- return nil unless send(base_time_field).present? && send(options[:end]).present?
41
-
42
- send(base_time_field) - send(options[:end])
43
- end
44
-
45
- define_method(:scheduled?) do
46
- send(base_time_field).present? && send(options[:start]).present? && send(options[:end]).present?
47
- end
48
-
49
- define_method(:partially_scheduled?) do
50
- send(base_time_field).present? || send(options[:start]).present? || send(options[:end]).present?
51
- end
52
-
53
- ###
54
- # Scopes
55
- #
56
- self.class.send(:define_method, :in_progress) do
57
- all.select(&:in_progress?)
58
- end
59
-
60
- self.class.send(:define_method, :in_progress?) do
61
- all.any?(&:in_progress?)
62
- end
63
-
64
- ###
65
- # Aliases
66
- #
67
- # Aliasing date methods to make code more readable
68
- instance_eval do
69
- alias active? in_progress?
70
- alias active in_progress
71
- end
72
-
73
- base_timeframe start_date_field: start_date_field,
74
- start_time_field: start_time_field,
75
- end_date_field: end_date_field,
76
- end_time_field: end_time_field
77
-
78
- private
79
- define_method(:has_absolute_timeframe?) do
80
- scheduled?
81
- end
82
-
83
- define_method(:duration_in_seconds) do
84
- return nil unless send(options[:start]).present? && send(options[:end]).present?
85
-
86
- send(options[:start]) - send(options[:end])
87
- end
88
- end
89
- end
90
-
91
- def self.included(base)
92
- base.extend Chronological::Base
93
- base.extend ClassMethods
94
- end
95
- end
96
- end
data/spec/base_spec.rb DELETED
@@ -1,230 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class BaseChronologicable < ActiveRecord::Base
4
- extend Chronological::Base
5
-
6
- base_timeframe :start_date_field => :started_on,
7
- :start_time_field => :started_at,
8
- :end_date_field => :ended_on,
9
- :end_time_field => :ended_at
10
-
11
- private
12
- def has_absolute_timeframe?
13
- started_at.present? && ended_at.present?
14
- end
15
- end
16
-
17
- describe Chronological::Base do
18
- let(:started_at) { nil }
19
- let(:ended_at) { nil }
20
-
21
- let(:chronologicable) do
22
- BaseChronologicable.new(
23
- :started_at => started_at,
24
- :ended_at => ended_at
25
- )
26
- end
27
-
28
- describe '#started_on' do
29
- context 'when #started_at is set' do
30
- context 'to a string' do
31
- let(:started_at) { '2012-07-26 03:15:12' }
32
-
33
- it 'properly converts the date' do
34
- chronologicable.started_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
35
- end
36
- end
37
-
38
- context 'to a date' do
39
- let(:started_at) { Time.utc(2012, 7, 26, 3, 15, 12) }
40
-
41
- it 'properly converts the date' do
42
- chronologicable.started_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
43
- end
44
- end
45
- end
46
-
47
- context 'when #started_at is not set' do
48
- let(:started_at) { nil }
49
-
50
- it 'is nil' do
51
- chronologicable.started_on.should be_nil
52
- end
53
- end
54
- end
55
-
56
- describe '#ended_on' do
57
- context 'when #ended_at is set' do
58
- context 'to a string' do
59
- let(:ended_at) { '2012-07-26 03:15:12' }
60
-
61
- it 'properly converts the date' do
62
- chronologicable.ended_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
63
- end
64
- end
65
-
66
- context 'to a date' do
67
- let(:ended_at) { Time.utc(2012, 7, 26, 3, 15, 12) }
68
-
69
- it 'properly converts the date' do
70
- chronologicable.ended_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
71
- end
72
- end
73
- end
74
-
75
- context 'when #ended_at is not set' do
76
- let(:ended_at) { nil }
77
-
78
- it 'is nil' do
79
- chronologicable.ended_on.should be_nil
80
- end
81
- end
82
- end
83
-
84
- describe '#duration' do
85
- context 'when the chronologicable represents something with a duration' do
86
- before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(6263) }
87
-
88
- it 'is a hash with the correct hours' do
89
- chronologicable.duration[:hours].should eql 1
90
- end
91
-
92
- it 'is a hash with the correct minutes' do
93
- chronologicable.duration[:minutes].should eql 44
94
- end
95
-
96
- it 'is a hash with the correct seconds' do
97
- chronologicable.duration[:seconds].should eql 23
98
- end
99
- end
100
-
101
- context 'when the chronologicable represents something with an even second time duration' do
102
- before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(6240) }
103
-
104
- it 'is a hash with the correct hours' do
105
- chronologicable.duration[:hours].should eql 1
106
- end
107
-
108
- it 'is a hash with the correct minutes' do
109
- chronologicable.duration[:minutes].should eql 44
110
- end
111
-
112
- it 'is a hash with the correct seconds' do
113
- chronologicable.duration[:seconds].should eql 0
114
- end
115
- end
116
-
117
- context 'when the chronologicable represents something with an even minute time duration' do
118
- before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(3600) }
119
-
120
- it 'is a hash with the correct hours' do
121
- chronologicable.duration[:hours].should eql 1
122
- end
123
-
124
- it 'is a hash with the correct minutes' do
125
- chronologicable.duration[:minutes].should eql 0
126
- end
127
-
128
- it 'is a hash with the correct seconds' do
129
- chronologicable.duration[:seconds].should eql 0
130
- end
131
- end
132
-
133
- context 'when the chronologicable represents something with a zero duration' do
134
- before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(0) }
135
-
136
- it 'is a hash with the correct hours' do
137
- chronologicable.duration[:hours].should eql 0
138
- end
139
-
140
- it 'is a hash with the correct minutes' do
141
- chronologicable.duration[:minutes].should eql 0
142
- end
143
-
144
- it 'is a hash with the correct seconds' do
145
- chronologicable.duration[:seconds].should eql 0
146
- end
147
- end
148
-
149
- context 'when duration in seconds returns an empty value' do
150
- before { chronologicable.should_receive(:duration_in_seconds).and_return(nil) }
151
-
152
- it 'is an empty hash' do
153
- chronologicable.duration.should eql Hash.new
154
- end
155
- end
156
- end
157
-
158
- describe '#in_progress?', :timecop => true do
159
- let(:later) { Time.local(2012, 7, 26, 6, 0, 26) }
160
- let(:now) { Time.local(2012, 7, 26, 6, 0, 25) }
161
- let(:past) { Time.local(2012, 7, 26, 6, 0, 24) }
162
-
163
- before { Timecop.freeze(now) }
164
-
165
- context 'when it does not have an absolute timeframe' do
166
- before { chronologicable.should_receive(:has_absolute_timeframe?).and_return(false) }
167
-
168
- it 'is false' do
169
- chronologicable.should_not be_in_progress
170
- end
171
- end
172
-
173
- context 'when it has already started' do
174
- let(:started_at) { past }
175
-
176
- context 'and already ended' do
177
- let(:ended_at) { past }
178
-
179
- it 'is false' do
180
- chronologicable.should_not be_in_progress
181
- end
182
- end
183
-
184
- context 'and ends now' do
185
- let(:ended_at) { now }
186
-
187
- it 'is false' do
188
- chronologicable.should_not be_in_progress
189
- end
190
- end
191
-
192
- context 'and ends later' do
193
- let(:ended_at) { later }
194
-
195
- it 'is true' do
196
- chronologicable.should be_in_progress
197
- end
198
- end
199
- end
200
-
201
- context 'when there is a chronologicable that starts now' do
202
- let(:started_at) { now }
203
-
204
- context 'and ends now' do
205
- let(:ended_at) { now }
206
-
207
- it 'is false' do
208
- chronologicable.should_not be_in_progress
209
- end
210
- end
211
-
212
- context 'and ends later' do
213
- let(:ended_at) { later }
214
-
215
- it 'is true' do
216
- chronologicable.should be_in_progress
217
- end
218
- end
219
- end
220
-
221
- context 'when there is a chronologicable that has not yet started' do
222
- let(:started_at) { later }
223
- let(:ended_at) { later }
224
-
225
- it 'is false' do
226
- chronologicable.should_not be_in_progress
227
- end
228
- end
229
- end
230
- end