by_star 0.2.5 → 0.3.0

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,23 @@
1
+ module ByStar
2
+ module Calculations
3
+ include Count
4
+ include Sum
5
+
6
+ private
7
+ def work_out_month(time, options = {})
8
+ year = options[:year] ||= Time.zone.now.year
9
+ # Work out what actual month is.
10
+ month = if time.is_a?(Numeric) && (1..12).include?(time)
11
+ time
12
+ elsif valid_time_or_date?(time)
13
+ year = time.year
14
+ time.month
15
+ elsif time.is_a?(String) && Date::MONTHNAMES.include?(time)
16
+ Date::MONTHNAMES.index(time)
17
+ else
18
+ raise ParseError, "Value is not an integer (between 1 and 12), time object or string (make sure you typed the name right)."
19
+ end
20
+ [year, month]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ module ByStar
2
+ module Calculations
3
+ module Count
4
+ def count_by_year(field=nil, year=Time.now.year, options={})
5
+ count(field, :conditions => conditions_for_range(start_of_year(year), end_of_year(year), options))
6
+ end
7
+
8
+ def count_by_month(field=nil, month=Time.now.month, options={})
9
+ year, month = work_out_month(month, options)
10
+ count(field, :conditions => conditions_for_range(start_of_month(month, year), end_of_month(month, year), options))
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module ByStar
2
+ module Calculations
3
+ module Sum
4
+ def sum_by_year(field, year=Time.zone.now.year, options={})
5
+ sum(field, :conditions => conditions_for_range(start_of_year(year), end_of_year(year), options))
6
+ end
7
+
8
+ def sum_by_month(field, month=Time.zone.now.month, options={})
9
+ year, month = work_out_month(month, options)
10
+ sum(field, :conditions => conditions_for_range(start_of_month(month, year), end_of_month(month, year), options))
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ module ByStar
2
+ module RangeCalculations
3
+
4
+ private
5
+
6
+ def start_of_year(year=Time.now.year)
7
+ Time.utc(year, 1, 1)
8
+ end
9
+
10
+ def end_of_year(year=Time.now.year)
11
+ start_of_year.end_of_year
12
+ end
13
+
14
+ def start_of_month(month, year=Time.now.year)
15
+ Time.utc(year, month, 1)
16
+ end
17
+
18
+ def end_of_month(month, year=Time.now.year)
19
+ start_of_month(month, year).end_of_month
20
+ end
21
+ end
22
+
23
+ end
data/lib/shared.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Shared
2
+ def conditions_for_range(start_time, end_time, options = {})
3
+ field = connection.quote_table_name(table_name) << '.' << connection.quote_column_name(options[:field] || "created_at")
4
+ ["#{field} >= ? AND #{field} <= ?", start_time.utc, end_time.utc]
5
+ end
6
+ end
data/lib/time_ext.rb ADDED
@@ -0,0 +1,20 @@
1
+ class Time
2
+ def beginning_of_weekend
3
+ friday = case self.wday
4
+ when 0
5
+ self.end_of_week.beginning_of_day.advance(:days => -2)
6
+ when 5
7
+ self.beginning_of_day
8
+ else
9
+ self.beginning_of_week.advance(:days => 4)
10
+ end
11
+ # 3pm, Friday.
12
+ (friday + 15.hours)
13
+ end
14
+
15
+ def end_of_weekend
16
+ # 3am, Monday.
17
+ # LOL I CHEATED.
18
+ beginning_of_weekend + 3.days - 12.hours
19
+ end
20
+ end
data/lib/vanilla.rb ADDED
@@ -0,0 +1,273 @@
1
+ module ByStar
2
+ module Vanilla
3
+ # Examples:
4
+ # by_year(2010)
5
+ # # 2-digit year:
6
+ # by_year(10)
7
+ # # Time or Date object:
8
+ # by_year(time)
9
+ # # String:
10
+ # by_year("2010")
11
+ def by_year(time=Time.zone.now.year, options={}, &block)
12
+ year = work_out_year(time)
13
+ start_time = start_of_year(year)
14
+ end_time = start_time.end_of_year
15
+ by_star(start_time, end_time, options, &block)
16
+ rescue ArgumentError
17
+ raise ParseError, "Invalid arguments detected, year may possibly be outside of valid range (1902-2039). This is no longer a problem on Ruby versions >= 1.8.7, so we recommend you upgrade to at least 1.8.7."
18
+ end
19
+
20
+ # Examples:
21
+ # by_month(1)
22
+ # by_month("January")
23
+ # by_month("January", :year => 2008)
24
+ # by_month(time)
25
+ def by_month(time=Time.zone.now.month, options={}, &block)
26
+ time = Time.zone.now.month if time.nil?
27
+ year, month = work_out_month(time, options)
28
+
29
+ start_time = start_of_month(month, year)
30
+ end_time = start_time.end_of_month
31
+
32
+ by_star(start_time, end_time, options, &block)
33
+ end
34
+
35
+ # Examples:
36
+ # # 18th fortnight of 2004
37
+ # Post.by_fortnight(18, :year => 2004)
38
+ def by_fortnight(time=Time.zone.now, options = {}, &block)
39
+ time = parse(time)
40
+
41
+ # If options[:year] is passed in, use that year regardless.
42
+ year = work_out_year(options[:year]) if options[:year]
43
+ # If the first argument is a date or time, ask it for the year
44
+ year ||= time.year unless time.is_a?(Numeric)
45
+ # If the first argument is a fixnum, assume this year.
46
+ year ||= Time.zone.now.year
47
+
48
+ # Dodgy!
49
+ # Surely there's a method in Rails to do this.
50
+ start_time = if valid_time_or_date?(time)
51
+ time.beginning_of_year + (time.strftime("%U").to_i).weeks
52
+ elsif time.is_a?(Numeric) && time <= 26
53
+ Time.utc(year, 1, 1) + ((time.to_i) * 2).weeks
54
+ else
55
+ raise ParseError, "by_fortnight takes only a Time or Date object, a Fixnum (less than or equal to 26) or a Chronicable string."
56
+ end
57
+ start_time = start_time.beginning_of_week
58
+ end_time = start_time + 2.weeks
59
+ by_star(start_time, end_time, options, &block)
60
+ end
61
+
62
+ # Examples:
63
+ # # 36th week
64
+ # Post.by_week(36)
65
+ # Post.by_week(36.54)
66
+ # Post.by_week(36, :year => 2004)
67
+ # Post.by_week(<Time object>)
68
+ # Post.by_week(<Date object>)
69
+ # Post.by_week("next tuesday")
70
+ def by_week(time=Time.zone.now, options = {}, &block)
71
+ time = parse(time)
72
+
73
+ # If options[:year] is passed in, use that year regardless.
74
+ year = work_out_year(options[:year]) if options[:year]
75
+ # If the first argument is a date or time, ask it for the year
76
+ year ||= time.year unless time.is_a?(Numeric)
77
+ # If the first argument is a fixnum, assume this year.
78
+ year ||= Time.now.year
79
+
80
+ # Dodgy!
81
+ # Surely there's a method in Rails to do this.
82
+ start_time = if valid_time_or_date?(time)
83
+ weeks = time.strftime("%U").to_i
84
+ time.beginning_of_year
85
+ elsif time.is_a?(Numeric) && time < 53
86
+ weeks = time.to_i
87
+ Time.utc(year, 1, 1)
88
+ else
89
+ raise ParseError, "by_week takes only a Time or Date object, a Fixnum (less than or equal to 53) or a Chronicable string."
90
+ end
91
+ start_time += weeks.weeks
92
+ end_time = start_time + 1.week
93
+ by_star(start_time, end_time, options, &block)
94
+ end
95
+
96
+
97
+ # Examples:
98
+ # Post.by_weekend
99
+ # Post.by_weekend(Time.now + 5.days)
100
+ # Post.by_weekend(Date.today + 5)
101
+ # Post.by_weekend("next tuesday")
102
+ def by_weekend(time=Time.zone.now, options = {}, &block)
103
+ time = parse(time)
104
+ start_time = time.beginning_of_weekend
105
+ by_star(start_time, (start_time + 1.day).end_of_day, options, &block)
106
+ end
107
+
108
+
109
+ # Examples:
110
+ # Post.by_current_weekend
111
+ def by_current_weekend(options = {}, &block)
112
+ time = Time.zone.now
113
+ # Friday, 3pm
114
+ start_time = time.beginning_of_weekend
115
+ # Monday, 3am
116
+ end_time = time.end_of_weekend
117
+ by_star(start_time, end_time, options, &block)
118
+ end
119
+
120
+ # Examples:
121
+ # Post.by_current_work_week
122
+ def by_current_work_week(options = {}, &block)
123
+ time = Time.zone.now
124
+ # Monday, 3am
125
+ time = time + 1.week if time.wday == 6 || time.wday == 0
126
+ start_time = time.beginning_of_week + 3.hours
127
+ # Friday, 3pm
128
+ end_time = time.beginning_of_weekend
129
+ by_star(start_time, end_time, options, &block)
130
+ end
131
+
132
+
133
+ # Examples:
134
+ # Post.by_day
135
+ # Post.by_day(Time.yesterday)
136
+ # Post.by_day("next tuesday")
137
+ def by_day(time = Time.zone.now, options = {}, &block)
138
+ time = parse(time)
139
+ by_star(time.beginning_of_day, time.end_of_day, options, &block)
140
+ end
141
+ alias_method :today, :by_day
142
+
143
+ # Examples:
144
+ # Post.yesterday
145
+ # # 2 days ago:
146
+ # Post.yesterday(Time.yesterday)
147
+ # # day before next tuesday
148
+ # Post.yesterday("next tuesday")
149
+ def yesterday(time = Time.zone.now, options = {}, &block)
150
+ time = parse(time)
151
+ by_day(time.advance(:days => -1), options, &block)
152
+ end
153
+
154
+ # Examples:
155
+ # Post.tomorrow
156
+ # # 2 days from now:
157
+ # Post.tomorrow(Time.tomorrow)
158
+ # # day after next tuesday
159
+ # Post.tomorrow("next tuesday")
160
+ def tomorrow(time = Time.zone.now, options = {}, &block)
161
+ time = parse(time)
162
+ by_day(time.advance(:days => 1), options, &block)
163
+ end
164
+
165
+ # Scopes to records older than current or given time
166
+ # Post.past
167
+ # Post.past()
168
+ def past(time = Time.zone.now, options = {}, &block)
169
+ time = parse(time)
170
+ by_direction("<", time, options, &block)
171
+ end
172
+
173
+ # Scopes to records newer than current or given time
174
+ def future(time = Time.zone.now, options = {}, &block)
175
+ time = parse(time)
176
+ by_direction(">", time, options, &block)
177
+ end
178
+
179
+ private
180
+
181
+ def by_direction(condition, time, options = {}, &block)
182
+ field = connection.quote_table_name(table_name)
183
+ field << "." << connection.quote_column_name(options[:field] || "created_at")
184
+ with_scope(:find => { :conditions => ["#{field} #{condition} ?", time.utc] }) do
185
+ if block_given?
186
+ with_scope(:find => block.call) do
187
+ find(:all)
188
+ end
189
+ else
190
+ find(:all)
191
+ end
192
+ end
193
+ end
194
+
195
+ # scopes results between start_time and end_time
196
+ def by_star(start_time, end_time, options = {}, &block)
197
+ start_time = parse(start_time)
198
+ end_time = parse(end_time)
199
+
200
+ raise ParseError, "End time is before start time, searching like this will return no results." if end_time < start_time
201
+
202
+ with_scope(:find => { :conditions => conditions_for_range(start_time, end_time, options) }) do
203
+ if block_given?
204
+ with_scope(:find => block.call) do
205
+ find(:all)
206
+ end
207
+ else
208
+ find(:all)
209
+ end
210
+ end
211
+ end
212
+
213
+ alias :between :by_star
214
+ public :between
215
+
216
+ # This will work for the next 30 years (written in 2009)
217
+ def work_out_year(value)
218
+ case value
219
+ when 0..39
220
+ 2000 + value
221
+ when 40..99
222
+ 1900 + value
223
+ when nil
224
+ Time.zone.now.year
225
+ else
226
+ # We may be passed something that's not a straight out integer
227
+ # These things include: BigDecimals, Floats and Strings.
228
+ value.to_i
229
+ end
230
+ end
231
+
232
+ # Checks if the object is a Time, Date or TimeWithZone object.
233
+ def valid_time_or_date?(value)
234
+ value.is_a?(Time) || value.is_a?(Date) || value.is_a?(ActiveSupport::TimeWithZone)
235
+ end
236
+
237
+ def parse(object)
238
+ object = case object.class.to_s
239
+ when "NilClass"
240
+ o = Time.zone.now
241
+ when "String"
242
+ o = object
243
+ Chronic.parse(object, :now => Time.zone.now)
244
+ when "Date"
245
+ object.to_time(:utc)
246
+ else
247
+ object
248
+ end
249
+ raise ParseError, "Chronic couldn't work out #{o.inspect}; please be more precise." if object.nil?
250
+ object
251
+ end
252
+
253
+ def method_missing(method, *args)
254
+ if method.to_s =~ /^(as_of|up_to)_(.+)$/
255
+ method = $1
256
+ expr = $2.humanize
257
+ unless time = parse(expr)
258
+ raise ParseError, "Chronic couldn't work out #{expr.inspect}; please be more precise."
259
+ end
260
+
261
+ reference = args.first || Time.now
262
+
263
+ if "as_of" == method
264
+ between(time, reference)
265
+ else
266
+ between(reference, time)
267
+ end
268
+ else
269
+ super
270
+ end
271
+ end
272
+ end
273
+ end
data/spec/by_star_spec.rb CHANGED
@@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
  require 'by_star'
3
3
 
4
4
  describe Post do
5
-
5
+
6
6
  def stub_time(day=15, month=5, year=Time.zone.now.year, hour=0, minute=0)
7
7
  stub = "#{day}-#{month}-#{year} #{hour}:#{minute}".to_time
8
8
  Time.stub!(:now).and_return(stub)
@@ -26,479 +26,532 @@ describe Post do
26
26
  Post.send(method, *args).size
27
27
  end
28
28
 
29
+ ["mysql", "sqlite3"].each do |adapter|
30
+ ActiveRecord::Base.establish_connection(YAML::load_file(File.dirname(__FILE__) + "/database.yml")[adapter])
29
31
 
30
- describe "by year" do
31
- it "should be able to find all the posts in the current year" do
32
- size.should eql(Post.count - 1)
33
- end
32
+ describe "by year" do
33
+ it "should be able to find all the posts in the current year" do
34
+ size.should eql(Post.count - 1)
35
+ end
34
36
 
35
- it "should be able to find if given a string" do
36
- size(Time.zone.now.year.to_s).should eql(Post.count - 1)
37
- end
37
+ it "should be able to find if given a string" do
38
+ size(Time.zone.now.year.to_s).should eql(Post.count - 1)
39
+ end
38
40
 
39
- it "should be able to find a single post from last year" do
40
- size(Time.zone.now.year-1).should eql(1)
41
- end
41
+ it "should be able to find a single post from last year" do
42
+ size(Time.zone.now.year-1).should eql(1)
43
+ end
42
44
 
43
- it "should error when given an invalid year" do
44
- # This is broken on 1.8.6 (and previous versions), any patchlevel after & before 111
45
- major, minor, trivial = RUBY_VERSION.split(".").map(&:to_i)
46
- if major == 1 && ((minor == 8 && trivial <= 6) || (minor <= 8)) && RUBY_PATCHLEVEL.to_i > 111
47
- lambda { find(1901) }.should raise_error(ByStar::ParseError, "Invalid arguments detected, year may possibly be outside of valid range (1902-2039)")
48
- lambda { find(2039) }.should raise_error(ByStar::ParseError, "Invalid arguments detected, year may possibly be outside of valid range (1902-2039)")
49
- else
50
- find(1456).should be_empty
51
- find(1901).should be_empty
52
- find(2039).should be_empty
45
+ it "should error when given an invalid year" do
46
+ # This is broken on 1.8.6 (and previous versions), any patchlevel after & before 111
47
+ major, minor, trivial = RUBY_VERSION.split(".").map(&:to_i)
48
+ if major == 1 && ((minor == 8 && trivial <= 6) || (minor <= 8)) && RUBY_PATCHLEVEL.to_i > 111
49
+ lambda { find(1901) }.should raise_error(ByStar::ParseError, "Invalid arguments detected, year may possibly be outside of valid range (1902-2039)")
50
+ lambda { find(2039) }.should raise_error(ByStar::ParseError, "Invalid arguments detected, year may possibly be outside of valid range (1902-2039)")
51
+ else
52
+ find(1456).should be_empty
53
+ find(1901).should be_empty
54
+ find(2039).should be_empty
55
+ end
53
56
  end
54
- end
55
57
 
56
- it "should be able to use an alternative field" do
57
- Event.by_year(nil, :field => "start_time").size.should eql(8)
58
+ it "should be able to use an alternative field" do
59
+ Event.by_year(nil, :field => "start_time").size.should eql(8)
60
+ end
58
61
  end
59
- end
60
62
 
61
- describe "by month" do
63
+ describe "by month" do
62
64
 
63
- it "should be able to find posts for the current month" do
64
- stub_time
65
- size.should eql(8)
66
- end
65
+ it "should be able to find posts for the current month" do
66
+ stub_time
67
+ size.should eql(8)
68
+ end
67
69
 
68
- it "should be able to find a single post for January" do
69
- size("January").should eql(1)
70
- end
70
+ it "should be able to find a single post for January" do
71
+ size("January").should eql(1)
72
+ end
71
73
 
72
- it "should be able to find two posts for the 2nd month" do
73
- size(2).should eql(2)
74
- end
74
+ it "should be able to find two posts for the 2nd month" do
75
+ size(2).should eql(2)
76
+ end
75
77
 
76
- it "should be able to find three posts for the 3rd month, using time instance" do
77
- # Hack... if we're running this test during march there's going to be more posts than usual.
78
- # This is due to the #today, #yesterday and #tomorrow methods.
78
+ it "should be able to find three posts for the 3rd month, using time instance" do
79
+ # Hack... if we're running this test during march there's going to be more posts than usual.
80
+ # This is due to the #today, #yesterday and #tomorrow methods.
79
81
 
80
- size(Time.local(Time.zone.now.year, 3, 1)).should eql(3)
81
- end
82
+ size(Time.local(Time.zone.now.year, 3, 1)).should eql(3)
83
+ end
82
84
 
83
- it "should be able to find a single post from January last year" do
84
- size("January", :year => Time.zone.now.year - 1).should eql(1)
85
- end
85
+ it "should be able to find a single post from January last year" do
86
+ size("January", :year => Time.zone.now.year - 1).should eql(1)
87
+ end
86
88
 
87
- it "should fail when given incorrect months" do
88
- lambda { find(0) }.should raise_error(ByStar::ParseError)
89
- lambda { find(13) }.should raise_error(ByStar::ParseError)
90
- lambda { find("Ryan") }.should raise_error(ByStar::ParseError)
91
- lambda { find([1,2,3]) }.should raise_error(ByStar::ParseError)
92
- end
89
+ it "should fail when given incorrect months" do
90
+ lambda { find(0) }.should raise_error(ByStar::ParseError)
91
+ lambda { find(13) }.should raise_error(ByStar::ParseError)
92
+ lambda { find("Ryan") }.should raise_error(ByStar::ParseError)
93
+ lambda { find([1,2,3]) }.should raise_error(ByStar::ParseError)
94
+ end
93
95
 
94
- it "should be able to take decimals" do
95
- size(1.5).should eql(1)
96
- end
96
+ it "should be able to take decimals" do
97
+ size(1.5).should eql(1)
98
+ end
97
99
 
98
- it "should be able to use an alternative field" do
99
- stub_time(1, 12)
100
- Event.by_month(nil, :field => "start_time").size.should eql(1)
101
- end
100
+ it "should be able to use an alternative field" do
101
+ stub_time(1, 12)
102
+ Event.by_month(nil, :field => "start_time").size.should eql(1)
103
+ end
102
104
 
103
- it "should be able to specify the year as a string" do
104
- size(1, :year => (Time.zone.now.year - 1).to_s).should eql(1)
105
- end
105
+ it "should be able to specify the year as a string" do
106
+ size(1, :year => (Time.zone.now.year - 1).to_s).should eql(1)
107
+ end
106
108
 
107
- end
109
+ end
108
110
 
109
- describe "by fortnight" do
111
+ describe "by fortnight" do
110
112
 
111
- it "should be able to find posts in the current fortnight" do
112
- stub_time
113
- size.should eql(3)
114
- end
113
+ it "should be able to find posts in the current fortnight" do
114
+ stub_time
115
+ size.should eql(3)
116
+ end
115
117
 
116
- it "should be able to find posts in the 1st fortnight" do
117
- size(0).should eql(1)
118
- end
118
+ it "should be able to find posts in the 1st fortnight" do
119
+ size(0).should eql(1)
120
+ end
119
121
 
120
- it "should be able to find posts for a fortnight ago" do
121
- stub_time
122
- size(2.weeks.ago).should eql(5)
123
- end
122
+ it "should be able to find posts for a fortnight ago" do
123
+ stub_time
124
+ size(2.weeks.ago).should eql(5)
125
+ end
124
126
 
125
- it "should raise an error when given an invalid argument" do
126
- lambda { find(27) }.should raise_error(ByStar::ParseError, "by_fortnight takes only a Time or Date object, a Fixnum (less than or equal to 26) or a Chronicable string.")
127
- end
127
+ it "should raise an error when given an invalid argument" do
128
+ lambda { find(27) }.should raise_error(ByStar::ParseError, "by_fortnight takes only a Time or Date object, a Fixnum (less than or equal to 26) or a Chronicable string.")
129
+ end
128
130
 
129
- it "should be able to use an alternative field" do
130
- stub_time
131
- Event.by_fortnight(nil, :field => "start_time").size.should eql(0)
131
+ it "should be able to use an alternative field" do
132
+ stub_time
133
+ Event.by_fortnight(nil, :field => "start_time").size.should eql(0)
134
+ end
132
135
  end
133
- end
134
136
 
135
- describe "by week" do
137
+ describe "by week" do
136
138
 
137
- it "should be able to find posts in the current week" do
138
- stub_time
139
- size.should eql(3)
140
- end
139
+ it "should be able to find posts in the current week" do
140
+ stub_time
141
+ size.should eql(3)
142
+ end
141
143
 
142
- it "should be able to find posts in the 1st week" do
143
- size(0).should eql(1)
144
- end
144
+ it "should be able to find posts in the 1st week" do
145
+ size(0).should eql(1)
146
+ end
145
147
 
146
- it "should be able to find posts in the 1st week of last year" do
147
- size(0, :year => Time.zone.now.year-1).should eql(1)
148
- end
148
+ it "should be able to find posts in the 1st week of last year" do
149
+ size(0, :year => Time.zone.now.year-1).should eql(1)
150
+ end
149
151
 
150
- it "should not find any posts from a week ago" do
151
- stub_time
152
- size(1.week.ago).should eql(0)
153
- end
152
+ it "should not find any posts from a week ago" do
153
+ stub_time
154
+ size(1.week.ago).should eql(0)
155
+ end
154
156
 
155
- it "should be able to find posts by a given date" do
156
- stub_time
157
- size(1.week.ago.to_date).should eql(0)
158
- end
157
+ it "should be able to find posts by a given date" do
158
+ stub_time
159
+ size(1.week.ago.to_date).should eql(0)
160
+ end
159
161
 
160
- it "should find, not size the posts for the current week" do
161
- stub_time
162
- find.map(&:text).include?("The 'Current' Week")
163
- find.map(&:text).include?("Weekend of May")
164
- end
162
+ it "should find, not size the posts for the current week" do
163
+ stub_time
164
+ find.map(&:text).include?("The 'Current' Week")
165
+ find.map(&:text).include?("Weekend of May")
166
+ end
165
167
 
166
- it "should raise an error when given an invalid argument" do
167
- lambda { find(54) }.should raise_error(ByStar::ParseError, "by_week takes only a Time or Date object, a Fixnum (less than or equal to 53) or a Chronicable string.")
168
- end
168
+ it "should raise an error when given an invalid argument" do
169
+ lambda { find(54) }.should raise_error(ByStar::ParseError, "by_week takes only a Time or Date object, a Fixnum (less than or equal to 53) or a Chronicable string.")
170
+ end
169
171
 
170
- it "should be able to use an alternative field" do
171
- stub_time
172
- Event.by_week(nil, :field => "start_time").size.should eql(0)
173
- end
172
+ it "should be able to use an alternative field" do
173
+ stub_time
174
+ Event.by_week(nil, :field => "start_time").size.should eql(0)
175
+ end
174
176
 
175
- it "should find posts at the start of the year" do
176
- size(0).should eql(1)
177
- end
177
+ it "should find posts at the start of the year" do
178
+ size(0).should eql(1)
179
+ end
178
180
 
179
- it "should find posts at the end of the year" do
180
- size(Time.zone.now.end_of_year).should eql(1)
181
- end
181
+ it "should find posts at the end of the year" do
182
+ size(Time.zone.now.end_of_year).should eql(1)
183
+ end
182
184
 
183
- end
184
-
185
- describe "by weekend" do
186
- it "should be able to find the posts on the weekend of the 1st May" do
187
- stub_time(1, 8)
188
- size.should eql(8)
189
185
  end
186
+
187
+ describe "by weekend" do
188
+ it "should be able to find the posts on the weekend of the 1st May" do
189
+ stub_time(1, 8)
190
+ size.should eql(8)
191
+ end
190
192
 
191
- it "should be able to use an alternative field" do
192
- year = Time.zone.now.year
193
- stub_time(1, 8)
194
- Event.by_weekend(nil, :field => "start_time").size.should eql(1)
193
+ it "should be able to use an alternative field" do
194
+ year = Time.zone.now.year
195
+ stub_time(1, 8)
196
+ Event.by_weekend(nil, :field => "start_time").size.should eql(1)
197
+ end
195
198
  end
196
- end
197
199
 
198
- describe "by current weekend" do
199
- it "should work" do
200
- range_test do
201
- Post.by_current_weekend
200
+ describe "by current weekend" do
201
+ it "should work" do
202
+ range_test do
203
+ Post.by_current_weekend
204
+ end
202
205
  end
203
206
  end
204
- end
205
207
 
206
- describe "by current work week" do
207
- it "should work" do
208
- range_test do
209
- Post.by_current_work_week
208
+ describe "by current work week" do
209
+ it "should work" do
210
+ range_test do
211
+ Post.by_current_work_week
212
+ end
210
213
  end
211
214
  end
212
- end
213
215
 
214
- describe "by day" do
215
- it "should be able to find a post for today" do
216
- stub_time
217
- size.should eql(2)
218
- end
216
+ describe "by day" do
217
+ it "should be able to find a post for today" do
218
+ stub_time
219
+ size.should eql(2)
220
+ end
219
221
 
220
- it "should be able to find a post by a given date" do
221
- stub_time
222
- size(Date.today).should eql(2)
223
- end
222
+ it "should be able to find a post by a given date" do
223
+ stub_time
224
+ size(Date.today).should eql(2)
225
+ end
224
226
 
225
- it "should be able to use an alternative field" do
226
- Event.by_day(nil, :field => "start_time").size.should eql(1)
227
+ it "should be able to use an alternative field" do
228
+ Event.by_day(nil, :field => "start_time").size.should eql(1)
229
+ end
227
230
  end
228
- end
229
231
 
230
- describe "today" do
231
- it "should show the post for today" do
232
- find.map(&:text).should include("Today's post")
233
- end
232
+ describe "today" do
233
+ it "should show the post for today" do
234
+ find.map(&:text).should include("Today's post")
235
+ end
234
236
 
235
- it "should be able to use an alternative field" do
236
- # Test may occur on an event day.
237
- stub_time
238
- Event.today(nil, :field => "start_time").size.should eql(0)
239
- end
237
+ it "should be able to use an alternative field" do
238
+ # Test may occur on an event day.
239
+ stub_time
240
+ Event.today(nil, :field => "start_time").size.should eql(0)
241
+ end
240
242
 
241
- end
243
+ end
242
244
 
243
- describe "tomorrow" do
244
- it "should show the post for tomorrow" do
245
- find.map(&:text).should include("Tomorrow's post")
245
+ describe "tomorrow" do
246
+ it "should show the post for tomorrow" do
247
+ find.map(&:text).should include("Tomorrow's post")
248
+ end
246
249
  end
247
- end
248
250
 
249
- describe "yesterday" do
250
- it "should show the post for yesterday" do
251
- find.map(&:text).should include("Yesterday's post")
252
- end
251
+ describe "yesterday" do
252
+ it "should show the post for yesterday" do
253
+ find.map(&:text).should include("Yesterday's post")
254
+ end
253
255
 
254
- it "should be able find yesterday, given a Date" do
255
- find(Time.now).map(&:text).should include("Yesterday's post")
256
- end
256
+ it "should be able find yesterday, given a Date" do
257
+ find(Time.now).map(&:text).should include("Yesterday's post")
258
+ end
257
259
 
258
- it "should be able to use an alternative field" do
259
- # Test may occur on an event day.
260
- stub_time
261
- Event.yesterday(nil, :field => "start_time").size.should eql(0)
262
- end
260
+ it "should be able to use an alternative field" do
261
+ # Test may occur on an event day.
262
+ stub_time
263
+ Event.yesterday(nil, :field => "start_time").size.should eql(0)
264
+ end
263
265
 
264
- end
265
-
266
- describe "tomorrow" do
267
- it "should show the post for tomorrow" do
268
- find.map(&:text).should include("Tomorrow's post")
269
266
  end
267
+
268
+ describe "tomorrow" do
269
+ it "should show the post for tomorrow" do
270
+ find.map(&:text).should include("Tomorrow's post")
271
+ end
270
272
 
271
- it "should be able find tomorrow, given a Date" do
272
- find(Time.now).map(&:text).should include("Tomorrow's post")
273
- end
273
+ it "should be able find tomorrow, given a Date" do
274
+ find(Time.now).map(&:text).should include("Tomorrow's post")
275
+ end
274
276
 
275
- it "should be able to use an alternative field" do
276
- # Test may occur on an event day.
277
- stub_time
278
- Event.tomorrow(nil, :field => "start_time").size.should eql(0)
277
+ it "should be able to use an alternative field" do
278
+ # Test may occur on an event day.
279
+ stub_time
280
+ Event.tomorrow(nil, :field => "start_time").size.should eql(0)
281
+ end
279
282
  end
280
- end
281
283
 
282
- describe "past" do
284
+ describe "past" do
283
285
 
284
- before do
285
- stub_time
286
- end
286
+ before do
287
+ stub_time
288
+ end
287
289
 
288
- it "should show the correct number of posts in the past" do
289
- size.should eql(16)
290
- end
290
+ it "should show the correct number of posts in the past" do
291
+ size.should eql(16)
292
+ end
291
293
 
292
- it "should find for a given time" do
293
- size(Time.zone.now - 2.days).should eql(16)
294
- end
294
+ it "should find for a given time" do
295
+ size(Time.zone.now - 2.days).should eql(16)
296
+ end
295
297
 
296
- it "should find for a given date" do
297
- size(Date.today - 2).should eql(16)
298
- end
298
+ it "should find for a given date" do
299
+ size(Date.today - 2).should eql(16)
300
+ end
299
301
 
300
- it "should find for a given string" do
301
- size("next tuesday").should eql(19)
302
- end
302
+ it "should find for a given string" do
303
+ size("next tuesday").should eql(19)
304
+ end
303
305
 
304
- it "should be able to find all events before Ryan's birthday using a non-standard field" do
305
- Event.past("04-12-#{Time.zone.now.year}".to_time, :field => "start_time").size.should eql(7)
306
- end
306
+ it "should be able to find all events before Ryan's birthday using a non-standard field" do
307
+ Event.past("04-12-#{Time.zone.now.year}".to_time, :field => "start_time").size.should eql(7)
308
+ end
307
309
 
308
- end
309
-
310
- describe "future" do
311
- before do
312
- stub_time
313
310
  end
311
+
312
+ describe "future" do
313
+ before do
314
+ stub_time
315
+ end
314
316
 
315
- it "should show the correct number of posts in the future" do
316
- size.should eql(71)
317
- end
317
+ it "should show the correct number of posts in the future" do
318
+ size.should eql(71)
319
+ end
318
320
 
319
- it "should find for a given date" do
320
- size(Date.today - 2).should eql(73)
321
- end
321
+ it "should find for a given date" do
322
+ size(Date.today - 2).should eql(73)
323
+ end
322
324
 
323
- it "should find for a given string" do
324
- size("next tuesday").should eql(70)
325
- end
325
+ it "should find for a given string" do
326
+ size("next tuesday").should eql(70)
327
+ end
326
328
 
327
- it "should be able to find all events after Dad's birthday using a non-standard field" do
328
- Event.past("05-07-#{Time.zone.now.year}".to_time, :field => "start_time").size.should eql(1)
329
+ it "should be able to find all events after Dad's birthday using a non-standard field" do
330
+ Event.past("05-07-#{Time.zone.now.year}".to_time, :field => "start_time").size.should eql(1)
331
+ end
329
332
  end
330
- end
331
333
 
332
- describe "as of" do
333
- it "should be able to find posts as of 2 weeks ago" do
334
- stub_time
335
- Post.as_of_2_weeks_ago.size.should eql(7)
336
- end
334
+ describe "as of" do
335
+ it "should be able to find posts as of 2 weeks ago" do
336
+ stub_time
337
+ Post.as_of_2_weeks_ago.size.should eql(7)
338
+ end
337
339
 
338
- it "should be able to find posts as of 2 weeks before a given time" do
339
- stub_time
340
- Post.as_of_2_weeks_ago(Time.zone.now + 1.month).size.should eql(14)
341
- end
340
+ it "should be able to find posts as of 2 weeks before a given time" do
341
+ stub_time
342
+ Post.as_of_2_weeks_ago(Time.zone.now + 1.month).size.should eql(14)
343
+ end
342
344
 
343
- it "should error if given a date in the past far enough back" do
344
- lambda { Post.as_of_6_weeks_ago(Time.zone.now - 2.months) }.should raise_error(ByStar::ParseError, "End time is before start time, searching like this will return no results.")
345
- end
345
+ it "should error if given a date in the past far enough back" do
346
+ lambda { Post.as_of_6_weeks_ago(Time.zone.now - 2.months) }.should raise_error(ByStar::ParseError, "End time is before start time, searching like this will return no results.")
347
+ end
346
348
 
347
- it "should not do anything if given an invalid date" do
348
- lambda { Post.as_of_ryans_birthday }.should raise_error(ByStar::ParseError, "Chronic couldn't work out \"Ryans birthday\"; please be more precise.")
349
+ it "should not do anything if given an invalid date" do
350
+ lambda { Post.as_of_ryans_birthday }.should raise_error(ByStar::ParseError, "Chronic couldn't work out \"Ryans birthday\"; please be more precise.")
351
+ end
349
352
  end
350
- end
351
353
 
352
- describe "between" do
353
- it "should find posts between last tuesday and next tuesday" do
354
- stub_time
355
- size("last tuesday", "next tuesday").should eql(3)
356
- end
354
+ describe "between" do
355
+ it "should find posts between last tuesday and next tuesday" do
356
+ stub_time
357
+ size("last tuesday", "next tuesday").should eql(3)
358
+ end
357
359
 
358
- it "should find between two times" do
359
- stub_time
360
- size(Time.zone.now - 5.days, Time.zone.now + 5.days).should eql(3)
361
- end
360
+ it "should find between two times" do
361
+ stub_time
362
+ size(Time.zone.now - 5.days, Time.zone.now + 5.days).should eql(3)
363
+ end
362
364
 
363
- it "should find between two dates" do
364
- stub_time
365
- size(Date.today, Date.today + 5).should eql(3)
365
+ it "should find between two dates" do
366
+ stub_time
367
+ size(Date.today, Date.today + 5).should eql(3)
368
+ end
366
369
  end
367
- end
368
370
 
369
- describe "up to" do
370
- it "should be able to find posts up to 2 weeks from now" do
371
- stub_time
372
- Post.up_to_6_weeks_from_now.size.should eql(9)
373
- end
371
+ describe "up to" do
372
+ it "should be able to find posts up to 2 weeks from now" do
373
+ stub_time
374
+ Post.up_to_6_weeks_from_now.size.should eql(9)
375
+ end
374
376
 
375
- it "should be able to find posts up to 2 weeks from a given time" do
376
- stub_time
377
- Post.up_to_6_weeks_from_now(Time.zone.now - 1.month).size.should eql(14)
378
- end
377
+ it "should be able to find posts up to 2 weeks from a given time" do
378
+ stub_time
379
+ Post.up_to_6_weeks_from_now(Time.zone.now - 1.month).size.should eql(14)
380
+ end
379
381
 
380
- it "should error if given a date in the past" do
381
- lambda { Post.up_to_6_weeks_from_now(Time.zone.now + 2.months) }.should raise_error(ByStar::ParseError, "End time is before start time, searching like this will return no results.")
382
- end
382
+ it "should error if given a date in the past" do
383
+ lambda { Post.up_to_6_weeks_from_now(Time.zone.now + 2.months) }.should raise_error(ByStar::ParseError, "End time is before start time, searching like this will return no results.")
384
+ end
383
385
 
384
- it "should not do anything if given an invalid date" do
385
- lambda { Post.up_to_ryans_birthday }.should raise_error(ByStar::ParseError, "Chronic couldn't work out \"Ryans birthday\"; please be more precise.")
386
- end
386
+ it "should not do anything if given an invalid date" do
387
+ lambda { Post.up_to_ryans_birthday }.should raise_error(ByStar::ParseError, "Chronic couldn't work out \"Ryans birthday\"; please be more precise.")
388
+ end
387
389
 
388
- end
389
-
390
- # Because we override method_missing, we ensure that it still works as it should with this test.
391
- describe "method_missing" do
392
- it "should still work" do
393
- Post.find_by_text("Today's post").should_not be_nil
394
390
  end
391
+
392
+ # Because we override method_missing, we ensure that it still works as it should with this test.
393
+ describe "method_missing" do
394
+ it "should still work" do
395
+ Post.find_by_text("Today's post").should_not be_nil
396
+ end
395
397
 
396
- it "should raise a proper NoMethodError" do
397
- lambda { Post.idontexist }.should raise_error(NoMethodError, %r(^undefined method `idontexist'))
398
+ it "should raise a proper NoMethodError" do
399
+ lambda { Post.idontexist }.should raise_error(NoMethodError, %r(^undefined method `idontexist'))
400
+ end
398
401
  end
399
- end
400
402
 
401
- describe "named_scopes" do
402
- it "should be compatible" do
403
- Event.private.by_year(nil, :field => "start_time").size.should eql(1)
403
+ describe "named_scopes" do
404
+ it "should be compatible" do
405
+ Event.private.by_year(nil, :field => "start_time").size.should eql(1)
406
+ end
404
407
  end
405
- end
406
408
 
407
- describe "joins" do
408
- it "should not have ambiguous column names" do
409
- lambda { Post.by_month do
410
- { :joins => :tags }
411
- end }.should_not raise_error
409
+ describe "joins" do
410
+ it "should not have ambiguous column names" do
411
+ lambda { Post.by_month do
412
+ { :joins => :tags }
413
+ end }.should_not raise_error
414
+ end
412
415
  end
413
- end
414
416
 
415
417
 
416
- describe "nested find" do
417
-
418
- it "should be able to find posts after right now" do
419
- stub_time
420
- Post.by_current_work_week.size.should eql(2)
421
- Post.by_current_work_week do
422
- { :conditions => ["created_at > ?", Time.now] }
423
- end.size.should eql(0)
424
- end
418
+ describe "nested find" do
419
+
420
+ it "should be able to find posts after right now" do
421
+ stub_time
422
+ Post.by_current_work_week.size.should eql(2)
423
+ Post.by_current_work_week do
424
+ { :conditions => ["created_at > ?", Time.now] }
425
+ end.size.should eql(0)
426
+ end
425
427
 
426
- it "should be able to find a single post from last year with the tag 'ruby'" do
427
- Post.by_year(Time.zone.now.year - 1) do
428
- { :include => :tags, :conditions => ["tags.name = ?", 'ruby'] }
429
- end.size.should eql(1)
430
- end
428
+ it "should be able to find a single post from last year with the tag 'ruby'" do
429
+ Post.by_year(Time.zone.now.year - 1) do
430
+ { :include => :tags, :conditions => ["tags.name = ?", 'ruby'] }
431
+ end.size.should eql(1)
432
+ end
431
433
 
432
- it "should be able to find a single post from January last year with the tag 'ruby'" do
433
- Post.by_month("January", :year => Time.zone.now.year - 1) do
434
- { :include => :tags, :conditions => ["tags.name = ?", 'ruby'] }
435
- end.size.should eql(1)
436
- end
434
+ it "should be able to find a single post from January last year with the tag 'ruby'" do
435
+ Post.by_month("January", :year => Time.zone.now.year - 1) do
436
+ { :include => :tags, :conditions => ["tags.name = ?", 'ruby'] }
437
+ end.size.should eql(1)
438
+ end
437
439
 
438
- it "should be able to find a single post from the current fortnight with the tag 'may2'" do
439
- stub_time
440
- Post.by_fortnight do
441
- { :include => :tags, :conditions => ["tags.name = ?", 'may2'] }
442
- end.size.should eql(1)
443
- end
440
+ it "should be able to find a single post from the current fortnight with the tag 'may2'" do
441
+ stub_time
442
+ Post.by_fortnight do
443
+ { :include => :tags, :conditions => ["tags.name = ?", 'may2'] }
444
+ end.size.should eql(1)
445
+ end
444
446
 
445
- it "should be able to find a single post from the current week with the tag 'may2'" do
446
- stub_time
447
- Post.by_week do
448
- { :include => :tags, :conditions => ["tags.name = ?", 'may2'] }
449
- end.size.should eql(1)
450
- end
447
+ it "should be able to find a single post from the current week with the tag 'may2'" do
448
+ stub_time
449
+ Post.by_week do
450
+ { :include => :tags, :conditions => ["tags.name = ?", 'may2'] }
451
+ end.size.should eql(1)
452
+ end
451
453
 
452
- it "should be able to find a single post from the current weekend with the tag 'weekend'" do
453
- stub_time
454
- Post.by_weekend do
455
- { :include => :tags, :conditions => ["tags.name = ?", 'weekend'] }
456
- end.size.should eql(1)
457
- end
454
+ it "should be able to find a single post from the current weekend with the tag 'weekend'" do
455
+ stub_time
456
+ Post.by_weekend do
457
+ { :include => :tags, :conditions => ["tags.name = ?", 'weekend'] }
458
+ end.size.should eql(1)
459
+ end
458
460
 
459
- it "should be able to find a single post from the current day with the tag 'today'" do
460
- Post.by_day do
461
- { :include => :tags, :conditions => ["tags.name = ?", 'today'] }
462
- end.size.should eql(1)
463
- end
461
+ it "should be able to find a single post from the current day with the tag 'today'" do
462
+ Post.by_day do
463
+ { :include => :tags, :conditions => ["tags.name = ?", 'today'] }
464
+ end.size.should eql(1)
465
+ end
464
466
 
465
- it "should be able to find a single post from yesterday with the tag 'yesterday'" do
466
- Post.yesterday do
467
- { :include => :tags, :conditions => ["tags.name = ?", 'yesterday'] }
468
- end.size.should eql(1)
469
- end
467
+ it "should be able to find a single post from yesterday with the tag 'yesterday'" do
468
+ Post.yesterday do
469
+ { :include => :tags, :conditions => ["tags.name = ?", 'yesterday'] }
470
+ end.size.should eql(1)
471
+ end
470
472
 
471
473
 
472
- it "should be able to find a single post from tomorrow with the tag 'tomorrow'" do
473
- Post.tomorrow do
474
- { :include => :tags, :conditions => ["tags.name = ?", 'tomorrow'] }
475
- end.size.should eql(1)
476
- end
474
+ it "should be able to find a single post from tomorrow with the tag 'tomorrow'" do
475
+ Post.tomorrow do
476
+ { :include => :tags, :conditions => ["tags.name = ?", 'tomorrow'] }
477
+ end.size.should eql(1)
478
+ end
477
479
 
478
- it "should be able to find a single post from the past with the tag 'yesterday'" do
479
- Post.past do
480
- { :include => :tags, :conditions => ["tags.name = ?", 'yesterday'] }
481
- end.size.should eql(1)
482
- end
480
+ it "should be able to find a single post from the past with the tag 'yesterday'" do
481
+ Post.past do
482
+ { :include => :tags, :conditions => ["tags.name = ?", 'yesterday'] }
483
+ end.size.should eql(1)
484
+ end
483
485
 
484
- it "should be able to find a single post from the future with the tag 'tomorrow'" do
485
- Post.future do
486
- { :include => :tags, :conditions => ["tags.name = ?", 'tomorrow'] }
487
- end.size.should eql(1)
488
- end
486
+ it "should be able to find a single post from the future with the tag 'tomorrow'" do
487
+ Post.future do
488
+ { :include => :tags, :conditions => ["tags.name = ?", 'tomorrow'] }
489
+ end.size.should eql(1)
490
+ end
489
491
 
490
- end
492
+ end
491
493
 
492
- describe Time do
493
- it "should work out the beginning of a weekend (Friday 3pm)" do
494
- range_test do
495
- Time.now.beginning_of_weekend.strftime("%A %I:%M%p").should eql("Friday 03:00PM")
494
+ describe "Calculations" do
495
+ describe "Sum" do
496
+ describe "by year" do
497
+ it "current year" do
498
+ stub_time
499
+ Invoice.sum_by_year(:value).should eql(374000)
500
+ end
501
+ end
502
+
503
+ describe "by month" do
504
+ it "current month" do
505
+ stub_time
506
+ Invoice.sum_by_month(:value).should eql(15000)
507
+ end
508
+ end
496
509
  end
510
+
511
+ describe "Count" do
512
+ describe "by year" do
513
+ it "current year" do
514
+ Invoice.count_by_year.should eql(79)
515
+ end
516
+
517
+ it "using a field" do
518
+ Invoice.count_by_year(:number).should eql(Invoice.by_year.size-1)
519
+ end
520
+
521
+ it "different year" do
522
+ Invoice.count_by_year(:all, 2008)
523
+ end
524
+ end
525
+
526
+ describe "by month" do
527
+ it "current month" do
528
+ Invoice.count_by_month
529
+ end
530
+
531
+ it "using a field" do
532
+ Invoice.count_by_month(:number).should eql(Invoice.by_month.size-1)
533
+ end
534
+
535
+ it "different month" do
536
+ stub_time
537
+ Invoice.count_by_month(:all, 9).should eql(9)
538
+ end
539
+ end
540
+ end
541
+
497
542
  end
543
+
544
+ describe Time do
545
+ it "should work out the beginning of a weekend (Friday 3pm)" do
546
+ range_test do
547
+ Time.now.beginning_of_weekend.strftime("%A %I:%M%p").should eql("Friday 03:00PM")
548
+ end
549
+ end
498
550
 
499
- it "should work out the end of a weekend (Monday 3am)" do
500
- range_test do
501
- Time.now.end_of_weekend.strftime("%A %I:%M%p").should eql("Monday 03:00AM")
551
+ it "should work out the end of a weekend (Monday 3am)" do
552
+ range_test do
553
+ Time.now.end_of_weekend.strftime("%A %I:%M%p").should eql("Monday 03:00AM")
554
+ end
502
555
  end
503
556
  end
504
557
  end