chronological 0.0.9 → 1.0.0beta1

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.
@@ -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