acts_as_flux_capacitor 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +11 -0
- data/Manifest.txt +1 -0
- data/lib/acts_as_flux_capacitor/acts_as_flux_capacitor.rb +24 -33
- data/lib/acts_as_flux_capacitor/core_class_extensions.rb +11 -9
- data/lib/acts_as_flux_capacitor/range_overlap.rb +1 -14
- data/lib/acts_as_flux_capacitor/temporal.rb +36 -31
- data/lib/acts_as_flux_capacitor/version.rb +2 -2
- data/spec/acts_as_flux_capacitor_spec.rb +116 -2
- data/spec/report.html +45 -33
- data/spec/spec_helper.rb +1 -0
- data/spec/time_helper.rb +54 -0
- metadata +3 -2
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 0.6.0 2008-05-23
|
2
|
+
|
3
|
+
* WAAAY more hardcore spec'ng
|
4
|
+
* removed debugging printing to STDOUT
|
5
|
+
* removed unnessary helper methods
|
6
|
+
|
7
|
+
== 0.5.4 2008-05-22
|
8
|
+
|
9
|
+
* Added Range specs
|
10
|
+
* Refactored Range#overlaps? (thanks to Nick Ang)
|
11
|
+
|
1
12
|
== 0.5.3 2008-05-21
|
2
13
|
|
3
14
|
* Fixed git stuff
|
data/Manifest.txt
CHANGED
@@ -58,16 +58,13 @@ module HolmesLabs #:nodoc:
|
|
58
58
|
def find(*args)
|
59
59
|
options = args.extract_options!
|
60
60
|
|
61
|
-
current_time = options.delete(:current_time)
|
61
|
+
current_time = options.delete(:current_time) || Time.now
|
62
62
|
temporal_conditions = extract_temporal_conditions!(options)
|
63
63
|
sql_temporal = sql_generate_temporal(temporal_conditions,current_time)
|
64
64
|
|
65
|
-
puts temporal_conditions.size
|
66
|
-
puts sql_temporal
|
67
|
-
|
68
65
|
with_scope( :find => {
|
69
|
-
|
70
|
-
|
66
|
+
:conditions => sql_temporal ,
|
67
|
+
:order => sql_oldest_first }) do
|
71
68
|
original_find(*(args << options))
|
72
69
|
end
|
73
70
|
end
|
@@ -87,9 +84,6 @@ private
|
|
87
84
|
temporal_conditions.merge!({key, options.delete(key)}) if CUSTOM_FIND_OPTIONS.include?(key)
|
88
85
|
end
|
89
86
|
|
90
|
-
|
91
|
-
require 'pp'# ; pp "(#{temporal_conditions.class}) #{temporal_conditions.first.keys}: #{temporal_conditions.first.values}"
|
92
|
-
pp temporal_conditions
|
93
87
|
temporal_conditions
|
94
88
|
end
|
95
89
|
end
|
@@ -97,59 +91,59 @@ private
|
|
97
91
|
module QueryGenerators
|
98
92
|
private
|
99
93
|
|
100
|
-
def sql_before(some_time, current_time
|
94
|
+
def sql_before(some_time, current_time)
|
101
95
|
# table_name comes from ActiveRecord.
|
102
96
|
"#{table_name}.ends_at < '#{some_time.to_s(:db)}'"
|
103
97
|
end
|
104
98
|
alias sql_to sql_before
|
105
99
|
alias sql_ends_before sql_before
|
106
100
|
|
107
|
-
def sql_after(some_time , current_time
|
101
|
+
def sql_after(some_time , current_time)
|
108
102
|
# table_name comes from ActiveRecord.
|
109
103
|
"#{table_name}.begins_at > '#{some_time.to_s(:db)}'"
|
110
104
|
end
|
111
105
|
alias sql_from sql_after
|
112
106
|
alias sql_begins_after sql_after
|
113
107
|
|
114
|
-
def sql_at(some_time , current_time
|
115
|
-
sql_join_conditions([ sql_starts_before( some_time),
|
116
|
-
sql_ends_after( some_time)])
|
108
|
+
def sql_at(some_time , current_time)
|
109
|
+
sql_join_conditions([ sql_starts_before( some_time , current_time),
|
110
|
+
sql_ends_after( some_time , current_time)])
|
117
111
|
end
|
118
112
|
|
119
|
-
def sql_ends_after(some_time
|
113
|
+
def sql_ends_after(some_time, current_time)
|
120
114
|
"#{table_name}.ends_at > '#{some_time.to_s(:db)}'"
|
121
115
|
end
|
122
116
|
|
123
|
-
def sql_starts_before(some_time , current_time
|
117
|
+
def sql_starts_before(some_time , current_time)
|
124
118
|
"#{table_name}.begins_at < '#{some_time.to_s(:db)}'"
|
125
119
|
end
|
126
120
|
|
127
|
-
def sql_past(is_true , current_time
|
121
|
+
def sql_past(is_true , current_time)
|
128
122
|
if is_true
|
129
|
-
sql_before(current_time)
|
123
|
+
sql_before(current_time, current_time)
|
130
124
|
else
|
131
|
-
sql_join_conditions_or([ sql_present(
|
132
|
-
sql_future(
|
125
|
+
sql_join_conditions_or([ sql_present( current_time),
|
126
|
+
sql_future( current_time)])
|
133
127
|
end
|
134
128
|
end
|
135
129
|
alias sql_ended sql_past
|
136
130
|
|
137
|
-
def sql_present(is_true , current_time
|
131
|
+
def sql_present(is_true , current_time)
|
138
132
|
if is_true
|
139
|
-
sql_at(current_time)
|
133
|
+
sql_at(current_time,current_time)
|
140
134
|
else
|
141
|
-
sql_join_conditions_or([ sql_past(
|
142
|
-
sql_future(
|
135
|
+
sql_join_conditions_or([ sql_past( current_time),
|
136
|
+
sql_future( current_time)])
|
143
137
|
end
|
144
138
|
end
|
145
139
|
alias sql_now sql_present
|
146
140
|
|
147
|
-
def sql_future(is_true, current_time
|
141
|
+
def sql_future(is_true, current_time)
|
148
142
|
if is_true
|
149
|
-
sql_after(current_time)
|
143
|
+
sql_after(current_time,current_time)
|
150
144
|
else
|
151
|
-
sql_join_conditions_or([ sql_present(
|
152
|
-
sql_past(
|
145
|
+
sql_join_conditions_or([ sql_present(current_time),
|
146
|
+
sql_past( current_time)])
|
153
147
|
end
|
154
148
|
end
|
155
149
|
|
@@ -165,15 +159,12 @@ private
|
|
165
159
|
"#{conditions.join(") OR (")}"
|
166
160
|
end
|
167
161
|
|
168
|
-
def sql_generate_temporal
|
162
|
+
def sql_generate_temporal temporal_conditions , current_time
|
169
163
|
sql_conditions = []
|
170
164
|
temporal_conditions.each do |condition,parameter|
|
171
|
-
|
172
|
-
sql_conditions << send("sql_#{condition}" , parameter , current_time)
|
165
|
+
sql_conditions << send("sql_#{condition}".to_sym , parameter, current_time)
|
173
166
|
end
|
174
167
|
|
175
|
-
require 'pp' ; pp sql_conditions
|
176
|
-
pp sql_join_conditions(sql_conditions)
|
177
168
|
sql_join_conditions(sql_conditions)
|
178
169
|
end
|
179
170
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Time
|
2
2
|
|
3
|
-
@@approx_eql_tolerance_in_seconds = 2
|
3
|
+
@@approx_eql_tolerance_in_seconds = 2
|
4
4
|
|
5
5
|
def Time.approx_eql_tolerance_in_seconds
|
6
6
|
@@approx_eql_tolerance_in_seconds
|
@@ -17,17 +17,19 @@ class Time
|
|
17
17
|
end
|
18
18
|
|
19
19
|
class Array
|
20
|
-
def within?
|
21
|
-
|
22
|
-
#
|
23
|
-
|
24
|
-
|
20
|
+
def within? tolerance
|
21
|
+
|
22
|
+
# thanks, nick ang!
|
23
|
+
unless self.size == 2
|
24
|
+
raise ArgumentError <<ERROR_STRING
|
25
|
+
within? only works with arrays of two numbers. do something like
|
26
|
+
([a,b,c].max,[a,b,c].min).within?(tolerance) as an implementation
|
27
|
+
for an array with more than two values
|
28
|
+
ERROR_STRING
|
29
|
+
end
|
25
30
|
|
26
31
|
difference = self.first - self.last
|
27
32
|
difference.abs <= tolerance
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
31
|
-
class Range
|
32
|
-
# to_event?
|
33
|
-
end
|
@@ -14,12 +14,7 @@ class Range
|
|
14
14
|
|
15
15
|
def overlap(other_range)
|
16
16
|
return 0 unless self.overlaps?(other_range)
|
17
|
-
|
18
|
-
overlap_range = greater_of(self.first,other_range.first)..smaller_of(self.last,other_range.last)
|
19
|
-
# puts "overlap range: #{overlap_range}"
|
20
|
-
# puts "greater of firsts: #{greater_of(self.first,other_range.first)}"
|
21
|
-
# puts "smaller of lasts: #{smaller_of(self.last,other_range.last)}"
|
22
|
-
return overlap_range
|
17
|
+
([self.first,other_range.first].max)..([self.last,other_range.last].min)
|
23
18
|
end
|
24
19
|
|
25
20
|
def size
|
@@ -43,13 +38,5 @@ private
|
|
43
38
|
|
44
39
|
def number_size # technically, off by infinity^(-1) when either or both endpoints are excluded. meh.
|
45
40
|
return self.last-self.first+1
|
46
|
-
end
|
47
|
-
|
48
|
-
def greater_of(num1,num2)
|
49
|
-
num1 > num2 ? num1 : num2
|
50
|
-
end
|
51
|
-
|
52
|
-
def smaller_of(num1,num2)
|
53
|
-
num1 < num2 ? num1 : num2
|
54
41
|
end
|
55
42
|
end
|
@@ -1,10 +1,5 @@
|
|
1
|
-
# require 'activesupport'
|
2
|
-
|
3
1
|
module Temporal
|
4
2
|
|
5
|
-
include ActiveSupport::CoreExtensions::Numeric::Time
|
6
|
-
include ActiveSupport::CoreExtensions::Time
|
7
|
-
|
8
3
|
def self.included(base) # :nodoc:
|
9
4
|
base.extend ClassMethods
|
10
5
|
base.extend ClassAndInstanceMethods
|
@@ -12,7 +7,6 @@ module Temporal
|
|
12
7
|
|
13
8
|
module ClassMethods
|
14
9
|
def range_between(obj,another_obj)
|
15
|
-
verify_temporal obj, another_obj
|
16
10
|
first_obj,second_obj = ordered_tuple(obj,another_obj)
|
17
11
|
beginning = extract_time(first_obj,:ends_at)
|
18
12
|
ending = extract_time(second_obj,:begins_at)
|
@@ -23,36 +17,50 @@ module Temporal
|
|
23
17
|
first_obj,second_obj = ordered_tuple(obj,another_obj)
|
24
18
|
beginning = extract_time(first_obj,:ends_at)
|
25
19
|
ending = extract_time(second_obj,:begins_at)
|
26
|
-
beginning.
|
20
|
+
beginning.before_or_at?(ending) ? ending - beginning : nil
|
27
21
|
end
|
28
22
|
|
29
|
-
def length_of_time_until(obj,
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
23
|
+
def length_of_time_until(obj,reference_obj=Time.now)
|
24
|
+
begins_at = extract_time(obj,:begins_at)
|
25
|
+
ends_at = extract_time(obj,:ends_at)
|
26
|
+
reference_point = extract_time(reference_obj,:ends_at)
|
27
|
+
|
28
|
+
time_until_begins = begins_at - reference_point
|
29
|
+
# has not started
|
30
|
+
if time_until_begins >= 0
|
31
|
+
time_until_begins
|
32
|
+
# has started, but not ended
|
33
|
+
elsif time_until_begins < 0 && reference_point.before?(ends_at)
|
34
|
+
0
|
35
|
+
# has ended
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
34
39
|
end
|
35
40
|
|
36
|
-
def length_of_time_since(obj,
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
+
def length_of_time_since(obj,reference_obj=Time.now)
|
42
|
+
begins_at = extract_time(obj,:begins_at)
|
43
|
+
ends_at = extract_time(obj,:ends_at)
|
44
|
+
|
45
|
+
reference_point = extract_time(reference_obj,:begins_at)
|
46
|
+
|
47
|
+
time_since_ended = reference_point - ends_at
|
48
|
+
has_started_but_not_ended = time_since_ended <= 0 && reference_point.after?(begins_at)
|
49
|
+
has_ended = time_since_ended >= 0
|
50
|
+
if has_ended
|
51
|
+
time_since_ended
|
52
|
+
elsif has_started_but_not_ended
|
53
|
+
0
|
54
|
+
else # has not started
|
55
|
+
nil
|
56
|
+
end
|
41
57
|
end
|
42
58
|
end
|
43
59
|
|
44
60
|
module ClassAndInstanceMethods
|
45
|
-
|
46
|
-
args.each do |obj|
|
47
|
-
unless obj.class.included_modules.include?(Temporal)
|
48
|
-
raise "This method requires objects it interacts with to have the Temporal module; instead received #{obj.class}."
|
49
|
-
end
|
50
|
-
end
|
51
|
-
return nil
|
52
|
-
end
|
61
|
+
|
53
62
|
private
|
54
63
|
def ordered_tuple(an_obj,other_obj)
|
55
|
-
verify_temporal an_obj , other_obj
|
56
64
|
if an_obj.before?(other_obj)
|
57
65
|
return an_obj,other_obj
|
58
66
|
else
|
@@ -64,7 +72,6 @@ module Temporal
|
|
64
72
|
# if object possesses accessor method, return obj.accessor.
|
65
73
|
# if not, return object. This is useful for fudging duck typing-
|
66
74
|
# style interaction between Events and Times/Dates, etc.
|
67
|
-
verify_temporal(obj)
|
68
75
|
obj.respond_to?(accessor.to_sym) ? obj.send(accessor.to_sym) : obj
|
69
76
|
end
|
70
77
|
end
|
@@ -76,7 +83,6 @@ module Temporal
|
|
76
83
|
end
|
77
84
|
|
78
85
|
def before?(obj)
|
79
|
-
verify_temporal(obj)
|
80
86
|
extract_time(self,:ends_at) < extract_time(obj,:begins_at)
|
81
87
|
end
|
82
88
|
|
@@ -85,7 +91,6 @@ module Temporal
|
|
85
91
|
end
|
86
92
|
|
87
93
|
def after?(obj)
|
88
|
-
verify_temporal(obj)
|
89
94
|
extract_time(self,:begins_at) > extract_time(obj,:ends_at)
|
90
95
|
end
|
91
96
|
|
@@ -103,12 +108,12 @@ module Temporal
|
|
103
108
|
end
|
104
109
|
|
105
110
|
def in_the_future?(time = Time.now)
|
106
|
-
extract_time(self,:
|
111
|
+
extract_time(self,:begins_at).after?(time)
|
107
112
|
end
|
108
113
|
alias future? in_the_future?
|
109
114
|
|
110
115
|
def in_the_past?(time=Time.now)
|
111
|
-
extract_time(self,:
|
116
|
+
extract_time(self,:ends_at).before?(time)
|
112
117
|
end
|
113
118
|
alias past? in_the_past?
|
114
119
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
2
|
|
3
|
+
# ...and no, it won't work to put everything in a giant Time.freeze block.
|
4
|
+
|
3
5
|
describe "The Temporal mixin" do
|
4
6
|
|
5
7
|
before(:all) do
|
@@ -15,34 +17,66 @@ describe "The Temporal mixin" do
|
|
15
17
|
|
16
18
|
it "should determine the length of time between two Temporal objects" do
|
17
19
|
Time.period_between(@present_time,@twenty_mins_later).should == 20.minutes
|
20
|
+
Time.period_between(@twenty_mins_later,@present_time).should == 20.minutes
|
21
|
+
|
22
|
+
Time.period_between(@twenty_mins_later,@twenty_mins_later).should == 0.minutes
|
18
23
|
end
|
19
24
|
|
20
25
|
it "should determine the length of time until a Temporal object" do
|
21
26
|
Time.length_of_time_until(@twenty_mins_later,@present_time).should == 20.minutes
|
27
|
+
Time.length_of_time_until(@present_time,@twenty_mins_later).should be_nil
|
28
|
+
Time.length_of_time_until(@present_time,@present_time).should == 0.minutes
|
29
|
+
|
30
|
+
Time.freeze do
|
31
|
+
Time.length_of_time_until(20.minutes.from_now).should == 20.minutes
|
32
|
+
Time.length_of_time_until(20.minutes.ago).should be_nil
|
33
|
+
Time.length_of_time_until(Time.now).should == 0.minutes
|
34
|
+
end
|
22
35
|
end
|
23
36
|
|
24
37
|
it "should determine if a temporal object is in the future" do
|
25
38
|
@twenty_mins_later.in_the_future?(@present_time).should be_true
|
26
39
|
@present_time.in_the_future?(@twenty_mins_later).should be_false
|
40
|
+
@present_time.in_the_future?(@present_time).should be_false
|
41
|
+
|
42
|
+
Time.freeze do
|
43
|
+
20.minutes.from_now.in_the_future?.should be_true
|
44
|
+
20.minutes.ago.in_the_future?.should be_false
|
45
|
+
Time.now.in_the_future?.should be_false
|
46
|
+
end
|
27
47
|
end
|
28
48
|
|
29
49
|
it "should determine the length of time since a Temporal object" do
|
30
50
|
Time.length_of_time_since(@present_time,@twenty_mins_later).should == 20.minutes
|
51
|
+
|
52
|
+
Time.freeze do
|
53
|
+
Time.length_of_time_since(20.minutes.ago).should == 20.minutes
|
54
|
+
Time.length_of_time_since(20.minutes.from_now).should be_nil
|
55
|
+
Time.length_of_time_since(Time.now).should == 0.minutes
|
56
|
+
end
|
31
57
|
end
|
32
58
|
|
33
59
|
it "should determine if a temporal object is in the past" do
|
34
60
|
@present_time.in_the_past?(@twenty_mins_later).should be_true
|
35
61
|
@twenty_mins_later.in_the_past?(@present_time).should be_false
|
62
|
+
|
63
|
+
Time.freeze do
|
64
|
+
10.minutes.ago.in_the_past?.should be_true
|
65
|
+
10.minutes.from_now.in_the_past?.should be_false
|
66
|
+
Time.now.in_the_future?.should be_false
|
67
|
+
end
|
36
68
|
end
|
37
69
|
|
38
70
|
it "should determine if one Temporal object is before another" do
|
39
71
|
@present_time.before?(@twenty_mins_later).should be_true
|
40
72
|
@twenty_mins_later.before?(@present_time).should be_false
|
73
|
+
@twenty_mins_later.before?(@twenty_mins_later).should be_false
|
41
74
|
end
|
42
75
|
|
43
76
|
it "should determine if one Temporal object is after another" do
|
44
|
-
@twenty_mins_later.
|
45
|
-
@present_time.
|
77
|
+
@twenty_mins_later.after?(@present_time).should be_true
|
78
|
+
@present_time.after?(@twenty_mins_later).should be_false
|
79
|
+
@present_time.after?(@present_time).should be_false
|
46
80
|
end
|
47
81
|
|
48
82
|
end
|
@@ -81,25 +115,57 @@ describe "The TimePeriod.find extensions" do
|
|
81
115
|
it "should find time_periods in the present" do
|
82
116
|
TimePeriod.find(:first,:present=>true ,:current_time => present_time).
|
83
117
|
happening_now?(present_time).should be_true
|
118
|
+
|
119
|
+
Time.freeze(present_time) do
|
120
|
+
TimePeriod.find(:first,:present=>true).happening_now?.should be_true
|
121
|
+
|
122
|
+
time_periods = TimePeriod.find(:all,:present=>true)
|
123
|
+
time_periods.size.should eql(2)
|
124
|
+
time_periods.each { |period| period.happening_now?.should be_true }
|
125
|
+
end
|
84
126
|
end
|
85
127
|
|
86
128
|
it "should find time_periods in the past" do
|
87
129
|
TimePeriod.find(:first,:past=>true ,:current_time => present_time).
|
88
130
|
in_the_past?(present_time).should be_true
|
131
|
+
|
132
|
+
Time.freeze(present_time) do
|
133
|
+
TimePeriod.find(:first,:past=>true).in_the_past?.should be_true
|
134
|
+
|
135
|
+
time_periods = TimePeriod.find(:all,:past=>true)
|
136
|
+
time_periods.size.should eql(1)
|
137
|
+
time_periods.each { |period| period.past?.should be_true }
|
138
|
+
end
|
89
139
|
end
|
90
140
|
|
91
141
|
it "should find time_periods in the future" do
|
92
142
|
TimePeriod.find(:first,:future=>true ,:current_time => present_time).
|
93
143
|
in_the_future?(present_time).should be_true
|
144
|
+
|
145
|
+
Time.freeze(present_time) do
|
146
|
+
TimePeriod.find(:first,:future=>true).in_the_future?.should be_true
|
147
|
+
|
148
|
+
time_periods = TimePeriod.find(:all,:future=>true)
|
149
|
+
time_periods.size.should eql(1)
|
150
|
+
time_periods.each { |period| period.future?.should be_true }
|
151
|
+
end
|
94
152
|
end
|
95
153
|
|
96
154
|
it "should find time_periods occuring at a specific time" do
|
97
155
|
TimePeriod.find(:first,:at=>future_time).at?(future_time).should be_true
|
156
|
+
|
157
|
+
time_periods = TimePeriod.find(:all,:at=>future_time)
|
158
|
+
time_periods.size.should eql(1)
|
159
|
+
time_periods.first.at?(future_time).should be_true
|
98
160
|
end
|
99
161
|
|
100
162
|
it "should find time_periods occuring within a specific range of time" do
|
101
163
|
TimePeriod.find(:first,:from => more_past_time , :to => more_future_time).
|
102
164
|
at?(present_time).should be_true
|
165
|
+
|
166
|
+
time_periods = TimePeriod.find(:all,:from => more_past_time , :to => more_future_time)
|
167
|
+
time_periods.size.should eql(1)
|
168
|
+
time_periods.first.at?(present_time).should be_true
|
103
169
|
end
|
104
170
|
|
105
171
|
end
|
@@ -107,6 +173,18 @@ end
|
|
107
173
|
describe "The TimePeriod comparison helpers" do
|
108
174
|
|
109
175
|
include TimePeriodFixtures
|
176
|
+
|
177
|
+
it "should determine if one time period is before another" do
|
178
|
+
present_period.before_or_at?(future_period).should be_true
|
179
|
+
future_period.before?(past_period).should be_false
|
180
|
+
present_period.before?(present_period).should be_false
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should determine if one time period is after another" do
|
184
|
+
future_period.after?(present_time).should be_true
|
185
|
+
present_time.after?(future_period).should be_false
|
186
|
+
past_period.after?(past_period).should be_false
|
187
|
+
end
|
110
188
|
|
111
189
|
it "should calculate the time between time_periods" do
|
112
190
|
TimePeriod.period_between(past_period,future_period).should == 140.minutes
|
@@ -133,6 +211,42 @@ end
|
|
133
211
|
|
134
212
|
describe "The TimePeriod status helpers" do
|
135
213
|
|
214
|
+
before(:all) do
|
215
|
+
@present_time = Time.parse "Sun May 18 16:41:58 2008"
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should determine the length of time until a time_period" do
|
219
|
+
Time.freeze(@present_time) do
|
220
|
+
Time.length_of_time_until(future_period).should == 20.minutes
|
221
|
+
Time.length_of_time_until(present_period).should == 0.minutes
|
222
|
+
Time.length_of_time_until(past_period).should be_nil
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should determine if a time_period is in the future" do
|
227
|
+
Time.freeze(@present_time) do
|
228
|
+
future_period.in_the_future?.should be_true
|
229
|
+
past_period.in_the_future?.should be_false
|
230
|
+
present_period.future?.should be_false
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should determine the length of time since a time_period ended" do
|
235
|
+
Time.freeze(@present_time) do
|
236
|
+
Time.length_of_time_since(past_period).should == 2.hours
|
237
|
+
Time.length_of_time_since(future_period).should be_nil
|
238
|
+
Time.length_of_time_since(present_period).should == 0.minutes
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should determine if a time_period is in the past" do
|
243
|
+
Time.freeze(@present_time) do
|
244
|
+
past_period.past?.should be_true
|
245
|
+
present_period.past?.should be_false
|
246
|
+
future_period.past?.should be_false
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
136
250
|
it "should determine if a time_period has started" do
|
137
251
|
past_period.started?(present_time).should be_true
|
138
252
|
present_period.started?(present_time).should be_true
|
data/spec/report.html
CHANGED
@@ -179,104 +179,116 @@ a {
|
|
179
179
|
<div class="example_group">
|
180
180
|
<dl>
|
181
181
|
<dt id="example_group_1">The Temporal mixin</dt>
|
182
|
-
<script type="text/javascript">moveProgressBar('
|
182
|
+
<script type="text/javascript">moveProgressBar('2.6');</script>
|
183
183
|
<dd class="spec passed"><span class="passed_spec_name">should make Time, Date and DateTime into Temporal objects</span></dd>
|
184
|
-
<script type="text/javascript">moveProgressBar('
|
184
|
+
<script type="text/javascript">moveProgressBar('5.2');</script>
|
185
185
|
<dd class="spec passed"><span class="passed_spec_name">should determine the length of time between two Temporal objects</span></dd>
|
186
|
-
<script type="text/javascript">moveProgressBar('
|
186
|
+
<script type="text/javascript">moveProgressBar('7.8');</script>
|
187
187
|
<dd class="spec passed"><span class="passed_spec_name">should determine the length of time until a Temporal object</span></dd>
|
188
|
-
<script type="text/javascript">moveProgressBar('
|
188
|
+
<script type="text/javascript">moveProgressBar('10.5');</script>
|
189
189
|
<dd class="spec passed"><span class="passed_spec_name">should determine if a temporal object is in the future</span></dd>
|
190
|
-
<script type="text/javascript">moveProgressBar('
|
190
|
+
<script type="text/javascript">moveProgressBar('13.1');</script>
|
191
191
|
<dd class="spec passed"><span class="passed_spec_name">should determine the length of time since a Temporal object</span></dd>
|
192
|
-
<script type="text/javascript">moveProgressBar('
|
192
|
+
<script type="text/javascript">moveProgressBar('15.7');</script>
|
193
193
|
<dd class="spec passed"><span class="passed_spec_name">should determine if a temporal object is in the past</span></dd>
|
194
|
-
<script type="text/javascript">moveProgressBar('
|
194
|
+
<script type="text/javascript">moveProgressBar('18.4');</script>
|
195
195
|
<dd class="spec passed"><span class="passed_spec_name">should determine if one Temporal object is before another</span></dd>
|
196
|
-
<script type="text/javascript">moveProgressBar('
|
196
|
+
<script type="text/javascript">moveProgressBar('21.0');</script>
|
197
197
|
<dd class="spec passed"><span class="passed_spec_name">should determine if one Temporal object is after another</span></dd>
|
198
198
|
</dl>
|
199
199
|
</div>
|
200
200
|
<div class="example_group">
|
201
201
|
<dl>
|
202
202
|
<dt id="example_group_2">The class TimePeriod < ActiveRecord::Base</dt>
|
203
|
-
<script type="text/javascript">moveProgressBar('
|
203
|
+
<script type="text/javascript">moveProgressBar('23.6');</script>
|
204
204
|
<dd class="spec passed"><span class="passed_spec_name">should be a flux capacitor</span></dd>
|
205
|
-
<script type="text/javascript">moveProgressBar('
|
205
|
+
<script type="text/javascript">moveProgressBar('26.3');</script>
|
206
206
|
<dd class="spec passed"><span class="passed_spec_name">should be a Temporal object</span></dd>
|
207
|
-
<script type="text/javascript">moveProgressBar('
|
207
|
+
<script type="text/javascript">moveProgressBar('28.9');</script>
|
208
208
|
<dd class="spec passed"><span class="passed_spec_name">should possess all four bitemporal database attributes</span></dd>
|
209
|
-
<script type="text/javascript">moveProgressBar('
|
209
|
+
<script type="text/javascript">moveProgressBar('31.5');</script>
|
210
210
|
<dd class="spec passed"><span class="passed_spec_name">should not be valid if either of the two time spans are 0 or less</span></dd>
|
211
211
|
</dl>
|
212
212
|
</div>
|
213
213
|
<div class="example_group">
|
214
214
|
<dl>
|
215
215
|
<dt id="example_group_3">The TimePeriod.find extensions</dt>
|
216
|
-
<script type="text/javascript">moveProgressBar('
|
216
|
+
<script type="text/javascript">moveProgressBar('34.2');</script>
|
217
217
|
<dd class="spec passed"><span class="passed_spec_name">should find time_periods in the present</span></dd>
|
218
|
-
<script type="text/javascript">moveProgressBar('
|
218
|
+
<script type="text/javascript">moveProgressBar('36.8');</script>
|
219
219
|
<dd class="spec passed"><span class="passed_spec_name">should find time_periods in the past</span></dd>
|
220
|
-
<script type="text/javascript">moveProgressBar('
|
220
|
+
<script type="text/javascript">moveProgressBar('39.4');</script>
|
221
221
|
<dd class="spec passed"><span class="passed_spec_name">should find time_periods in the future</span></dd>
|
222
|
-
<script type="text/javascript">moveProgressBar('
|
222
|
+
<script type="text/javascript">moveProgressBar('42.1');</script>
|
223
223
|
<dd class="spec passed"><span class="passed_spec_name">should find time_periods occuring at a specific time</span></dd>
|
224
|
-
<script type="text/javascript">moveProgressBar('
|
224
|
+
<script type="text/javascript">moveProgressBar('44.7');</script>
|
225
225
|
<dd class="spec passed"><span class="passed_spec_name">should find time_periods occuring within a specific range of time</span></dd>
|
226
226
|
</dl>
|
227
227
|
</div>
|
228
228
|
<div class="example_group">
|
229
229
|
<dl>
|
230
230
|
<dt id="example_group_4">The TimePeriod comparison helpers</dt>
|
231
|
-
<script type="text/javascript">moveProgressBar('
|
231
|
+
<script type="text/javascript">moveProgressBar('47.3');</script>
|
232
|
+
<dd class="spec passed"><span class="passed_spec_name">should determine if one time period is before another</span></dd>
|
233
|
+
<script type="text/javascript">moveProgressBar('50.0');</script>
|
234
|
+
<dd class="spec passed"><span class="passed_spec_name">should determine if one time period is after another</span></dd>
|
235
|
+
<script type="text/javascript">moveProgressBar('52.6');</script>
|
232
236
|
<dd class="spec passed"><span class="passed_spec_name">should calculate the time between time_periods</span></dd>
|
233
|
-
<script type="text/javascript">moveProgressBar('
|
237
|
+
<script type="text/javascript">moveProgressBar('55.2');</script>
|
234
238
|
<dd class="spec passed"><span class="passed_spec_name">should determine whether two time_periods overlap</span></dd>
|
235
|
-
<script type="text/javascript">moveProgressBar('
|
239
|
+
<script type="text/javascript">moveProgressBar('57.8');</script>
|
236
240
|
<dd class="spec passed"><span class="passed_spec_name">should determine the length of time by which two time_periods overlap</span></dd>
|
237
|
-
<script type="text/javascript">moveProgressBar('
|
241
|
+
<script type="text/javascript">moveProgressBar('60.5');</script>
|
238
242
|
<dd class="spec passed"><span class="passed_spec_name">should determine if two time_periods are back-to-back</span></dd>
|
239
|
-
<script type="text/javascript">moveProgressBar('
|
243
|
+
<script type="text/javascript">moveProgressBar('63.1');</script>
|
240
244
|
<dd class="spec passed"><span class="passed_spec_name">should determine if a time_period is between two other time_periods</span></dd>
|
241
245
|
</dl>
|
242
246
|
</div>
|
243
247
|
<div class="example_group">
|
244
248
|
<dl>
|
245
249
|
<dt id="example_group_5">The TimePeriod status helpers</dt>
|
246
|
-
<script type="text/javascript">moveProgressBar('
|
250
|
+
<script type="text/javascript">moveProgressBar('65.7');</script>
|
251
|
+
<dd class="spec passed"><span class="passed_spec_name">should determine the length of time until a time_period</span></dd>
|
252
|
+
<script type="text/javascript">moveProgressBar('68.4');</script>
|
253
|
+
<dd class="spec passed"><span class="passed_spec_name">should determine if a time_period is in the future</span></dd>
|
254
|
+
<script type="text/javascript">moveProgressBar('71.0');</script>
|
255
|
+
<dd class="spec passed"><span class="passed_spec_name">should determine the length of time since a time_period ended</span></dd>
|
256
|
+
<script type="text/javascript">moveProgressBar('73.6');</script>
|
257
|
+
<dd class="spec passed"><span class="passed_spec_name">should determine if a time_period is in the past</span></dd>
|
258
|
+
<script type="text/javascript">moveProgressBar('76.3');</script>
|
247
259
|
<dd class="spec passed"><span class="passed_spec_name">should determine if a time_period has started</span></dd>
|
248
|
-
<script type="text/javascript">moveProgressBar('
|
260
|
+
<script type="text/javascript">moveProgressBar('78.9');</script>
|
249
261
|
<dd class="spec passed"><span class="passed_spec_name">should determine how much time has elapsed since an event started</span></dd>
|
250
|
-
<script type="text/javascript">moveProgressBar('
|
262
|
+
<script type="text/javascript">moveProgressBar('81.5');</script>
|
251
263
|
<dd class="spec passed"><span class="passed_spec_name">should determine what percentage of time has elapsed since an event started</span></dd>
|
252
|
-
<script type="text/javascript">moveProgressBar('
|
264
|
+
<script type="text/javascript">moveProgressBar('84.2');</script>
|
253
265
|
<dd class="spec passed"><span class="passed_spec_name">should determine how much time is remaining until an event ends</span></dd>
|
254
|
-
<script type="text/javascript">moveProgressBar('
|
266
|
+
<script type="text/javascript">moveProgressBar('86.8');</script>
|
255
267
|
<dd class="spec passed"><span class="passed_spec_name">should determine what percentage of time is remaining until an event ends</span></dd>
|
256
|
-
<script type="text/javascript">moveProgressBar('
|
268
|
+
<script type="text/javascript">moveProgressBar('89.4');</script>
|
257
269
|
<dd class="spec passed"><span class="passed_spec_name">should determine if a time_period has ended</span></dd>
|
258
|
-
<script type="text/javascript">moveProgressBar('
|
270
|
+
<script type="text/javascript">moveProgressBar('92.1');</script>
|
259
271
|
<dd class="spec passed"><span class="passed_spec_name">should determine the duration of a time_period</span></dd>
|
260
272
|
</dl>
|
261
273
|
</div>
|
262
274
|
<div class="example_group">
|
263
275
|
<dl>
|
264
276
|
<dt id="example_group_6">The TimePeriod modification helpers</dt>
|
265
|
-
<script type="text/javascript">moveProgressBar('
|
277
|
+
<script type="text/javascript">moveProgressBar('94.7');</script>
|
266
278
|
<dd class="spec passed"><span class="passed_spec_name">should shift a time_period into the past or future</span></dd>
|
267
279
|
</dl>
|
268
280
|
</div>
|
269
281
|
<div class="example_group">
|
270
282
|
<dl>
|
271
283
|
<dt id="example_group_7">The Range overlap helpers</dt>
|
272
|
-
<script type="text/javascript">moveProgressBar('
|
284
|
+
<script type="text/javascript">moveProgressBar('97.3');</script>
|
273
285
|
<dd class="spec passed"><span class="passed_spec_name">should determine if two ranges do not overlap</span></dd>
|
274
286
|
<script type="text/javascript">moveProgressBar('100.0');</script>
|
275
287
|
<dd class="spec passed"><span class="passed_spec_name">should determine if two ranges do overlap</span></dd>
|
276
288
|
</dl>
|
277
289
|
</div>
|
278
|
-
<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>0.
|
279
|
-
<script type="text/javascript">document.getElementById('totals').innerHTML = "
|
290
|
+
<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>0.368839 seconds</strong>";</script>
|
291
|
+
<script type="text/javascript">document.getElementById('totals').innerHTML = "38 examples, 0 failures";</script>
|
280
292
|
</div>
|
281
293
|
</div>
|
282
294
|
</body>
|
data/spec/spec_helper.rb
CHANGED
@@ -11,6 +11,7 @@ require 'ruby-debug'
|
|
11
11
|
require 'activerecord'
|
12
12
|
require 'activesupport'
|
13
13
|
require 'spec/fixtures.rb'
|
14
|
+
require 'spec/time_helper.rb'
|
14
15
|
|
15
16
|
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
16
17
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/../log/debug.log")
|
data/spec/time_helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class Time
|
2
|
+
|
3
|
+
# this code adds a Time.freeze method to make time "stand still"
|
4
|
+
# during execution of a block. This can be helpful during testing of
|
5
|
+
# methods that depend on Time.new or Time.now
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# Time.freeze do
|
10
|
+
# puts Time.new.to_f
|
11
|
+
# # ... do stuff; real time passes
|
12
|
+
# puts Time.new.to_f # outputs same time as above
|
13
|
+
# end
|
14
|
+
# # ... time returns to normal
|
15
|
+
#
|
16
|
+
# An optional Time object may be passed to freeze to a specific time:
|
17
|
+
#
|
18
|
+
# Time.freeze(Time.at(2007, 11, 15)) do
|
19
|
+
# # ...
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# While inside the block, Time.frozen? will return true
|
23
|
+
|
24
|
+
class << self
|
25
|
+
|
26
|
+
def now
|
27
|
+
@time || orig_new
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method :orig_freeze, :freeze
|
31
|
+
alias_method :orig_new, :new
|
32
|
+
alias_method :new, :now
|
33
|
+
|
34
|
+
# makes time "stand still" during execution of a block. if no time is
|
35
|
+
# supplied, the current time is used. While in the block, Time.new and
|
36
|
+
# Time.now will always return the "frozen" value.
|
37
|
+
def freeze(time = nil)
|
38
|
+
raise "A block is required" unless block_given?
|
39
|
+
begin
|
40
|
+
prev = @time
|
41
|
+
@time = time || now
|
42
|
+
yield
|
43
|
+
ensure
|
44
|
+
@time = prev
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def frozen?
|
49
|
+
!@time.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_flux_capacitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Cropcho
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-05-
|
12
|
+
date: 2008-05-23 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- spec/schema.rb
|
53
53
|
- spec/spec.opts
|
54
54
|
- spec/spec_helper.rb
|
55
|
+
- spec/time_helper.rb
|
55
56
|
- tasks/deployment.rake
|
56
57
|
- tasks/environment.rake
|
57
58
|
- tasks/rspec.rake
|