by_star 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/by_star.rb CHANGED
@@ -7,18 +7,18 @@ require 'vanilla'
7
7
  Dir[File.dirname(__FILE__) + '/calculations/*.rb'].each { |file| require file }
8
8
  require 'calculations'
9
9
  module ByStar
10
-
10
+
11
11
  def self.included(base)
12
12
  base.extend ClassMethods
13
13
  end
14
-
14
+
15
15
  module ClassMethods
16
16
  include RangeCalculations
17
17
  include Shared
18
18
  include Vanilla
19
19
  include Calculations
20
20
  end
21
-
21
+
22
22
  class ParseError < Exception; end
23
23
  class MonthNotFound < Exception; end
24
24
  end
data/lib/calculations.rb CHANGED
@@ -2,7 +2,7 @@ module ByStar
2
2
  module Calculations
3
3
  include Count
4
4
  include Sum
5
-
5
+
6
6
  private
7
7
  def work_out_month(time, year=Time.zone.now.year)
8
8
  year ||= Time.zone.now.year
@@ -7,7 +7,7 @@ module ByStar
7
7
  count(field, { :conditions => conditions_for_range(start_of_year(year), end_of_year(year), db_field) }.reverse_merge!(options))
8
8
  end
9
9
  end
10
-
10
+
11
11
  def count_by_month(field=nil, month=Time.now.month, options={}, &block)
12
12
  db_field = options.delete(:field)
13
13
  year, month = work_out_month(month, options.delete(:year))
@@ -13,7 +13,7 @@ module ByStar
13
13
  sum(field, { :conditions => conditions_for_range(start_of_month(month, year), end_of_month(month, year), options.delete(:field)) }.reverse_merge!(options))
14
14
  end
15
15
  end
16
-
16
+
17
17
  def sum_by_day(field, day=Time.zone.now, options={}, &block)
18
18
  scoped_by(block) do
19
19
  day = parse(day)
@@ -2,22 +2,22 @@ module ByStar
2
2
  module RangeCalculations
3
3
 
4
4
  private
5
-
5
+
6
6
  def start_of_year(year=Time.zone.now.year)
7
7
  Time.utc(year, 1, 1)
8
8
  end
9
-
9
+
10
10
  def end_of_year(year=Time.zone.now.year)
11
11
  start_of_year(year).end_of_year
12
12
  end
13
-
13
+
14
14
  def start_of_month(month, year=Timeow.year)
15
15
  Time.utc(year, month, 1)
16
16
  end
17
-
17
+
18
18
  def end_of_month(month, year=Time.now.year)
19
19
  start_of_month(month, year).end_of_month
20
20
  end
21
21
  end
22
-
22
+
23
23
  end
data/lib/shared.rb CHANGED
@@ -3,7 +3,7 @@ module Shared
3
3
  field = table_name << '.' << (field ? field.to_s : "created_at")
4
4
  ["#{field} >= ? AND #{field} <= ?", start_time.utc, end_time.utc]
5
5
  end
6
-
6
+
7
7
  private
8
8
  def scoped_by(options=nil, &block)
9
9
  if options && scope = options.call
data/lib/time_ext.rb CHANGED
@@ -11,7 +11,7 @@ class Time
11
11
  # 3pm, Friday.
12
12
  (friday + 15.hours)
13
13
  end
14
-
14
+
15
15
  def end_of_weekend
16
16
  # 3am, Monday.
17
17
  # LOL I CHEATED.
data/lib/vanilla.rb CHANGED
@@ -25,7 +25,7 @@ module ByStar
25
25
  def by_month(time=Time.zone.now.month, options={}, &block)
26
26
  time = Time.zone.now.month if time.nil?
27
27
  year, month = work_out_month(time, options.delete(:year))
28
-
28
+
29
29
  start_time = start_of_month(month, year)
30
30
  end_time = start_time.end_of_month
31
31
 
@@ -37,14 +37,14 @@ module ByStar
37
37
  # Post.by_fortnight(18, :year => 2004)
38
38
  def by_fortnight(time=Time.zone.now, options = {}, &block)
39
39
  time = parse(time)
40
-
40
+
41
41
  # If options[:year] is passed in, use that year regardless.
42
42
  year = work_out_year(options[:year]) if options[:year]
43
43
  # If the first argument is a date or time, ask it for the year
44
44
  year ||= time.year unless time.is_a?(Numeric)
45
45
  # If the first argument is a fixnum, assume this year.
46
46
  year ||= Time.zone.now.year
47
-
47
+
48
48
  # Dodgy!
49
49
  # Surely there's a method in Rails to do this.
50
50
  start_time = if valid_time_or_date?(time)
@@ -69,19 +69,19 @@ module ByStar
69
69
  # Post.by_week("next tuesday")
70
70
  def by_week(time=Time.zone.now, options = {}, &block)
71
71
  time = parse(time)
72
-
72
+
73
73
  # If options[:year] is passed in, use that year regardless.
74
74
  year = work_out_year(options.delete(:year)) if options[:year]
75
75
  # If the first argument is a date or time, ask it for the year
76
76
  year ||= time.year unless time.is_a?(Numeric)
77
77
  # If the first argument is a fixnum, assume this year.
78
78
  year ||= Time.zone.now.year
79
-
79
+
80
80
  # Dodgy!
81
81
  # Surely there's a method in Rails to do this.
82
82
  start_time = if valid_time_or_date?(time)
83
83
  weeks = time.strftime("%U").to_i
84
-
84
+
85
85
  # Sunday defines the start of the week.
86
86
  # Finds the sunday that defines the starting week of the year.
87
87
  # This is because AS +*.weeks helper works off the given time, which could be any day.
@@ -109,7 +109,6 @@ module ByStar
109
109
  time = parse(time)
110
110
  start_time = time.beginning_of_weekend
111
111
  end_time = (start_time + 1.day).end_of_day
112
- p start_time..end_time
113
112
  by_star(start_time, end_time, options, &block)
114
113
  end
115
114
 
@@ -185,36 +184,31 @@ module ByStar
185
184
  end
186
185
 
187
186
  private
188
-
187
+
189
188
  def by_direction(condition, time, options = {}, &block)
190
- field = options.delete(:field) || "created_at"
189
+ field = options.delete(:field) || "#{self.table_name}.created_at"
191
190
  ensure_valid_options(options)
192
- scoping = { :conditions => ["#{field} #{condition} ?", time.utc] }.merge(options)
193
- with_scope(:find => scoping) do
194
- scoped_by(block) do
195
- find(:all)
196
- end
197
- end
191
+ result = scoped({ :conditions => ["#{field} #{condition} ?", time.utc] }.merge(options))
192
+ result = result.scoped(block.call) if block_given?
193
+ result
198
194
  end
199
-
195
+
200
196
  # scopes results between start_time and end_time
201
197
  def by_star(start_time, end_time, options = {}, &block)
202
198
  start_time = parse(start_time)
203
199
  end_time = parse(end_time)
204
-
205
-
200
+
201
+
206
202
  raise ParseError, "End time is before start time, searching like this will return no results." if end_time < start_time
207
203
  field = options.delete(:field)
208
204
  ensure_valid_options(options)
209
-
205
+
210
206
  scoping = { :conditions => conditions_for_range(start_time, end_time, field) }.merge(options)
211
- with_scope(:find => scoping) do
212
- scoped_by(block) do
213
- find(:all)
214
- end
215
- end
207
+ result = scoped(scoping)
208
+ result = result.scoped(block.call) if block_given?
209
+ result
216
210
  end
217
-
211
+
218
212
  def ensure_valid_options(options)
219
213
  if respond_to?(:validate_find_options)
220
214
  validate_find_options(options)
@@ -222,10 +216,10 @@ module ByStar
222
216
  options.assert_valid_keys(ActiveRecord::SpawnMethods::VALID_FIND_OPTIONS)
223
217
  end
224
218
  end
225
-
219
+
226
220
  alias :between :by_star
227
221
  public :between
228
-
222
+
229
223
  # This will work for the next 30 years (written in 2009)
230
224
  def work_out_year(value)
231
225
  case value
@@ -241,12 +235,12 @@ module ByStar
241
235
  value.to_i
242
236
  end
243
237
  end
244
-
238
+
245
239
  # Checks if the object is a Time, Date or TimeWithZone object.
246
240
  def valid_time_or_date?(value)
247
241
  value.is_a?(Time) || value.is_a?(Date) || value.is_a?(ActiveSupport::TimeWithZone)
248
242
  end
249
-
243
+
250
244
  def parse(object)
251
245
  object = case object.class.to_s
252
246
  when "NilClass"
@@ -262,7 +256,7 @@ module ByStar
262
256
  raise ParseError, "Chronic couldn't work out #{o.inspect}; please be more precise." if object.nil?
263
257
  object
264
258
  end
265
-
259
+
266
260
  def method_missing(method, *args)
267
261
  if method.to_s =~ /^(as_of|up_to)_(.+)$/
268
262
  method = $1
@@ -270,9 +264,9 @@ module ByStar
270
264
  unless time = parse(expr)
271
265
  raise ParseError, "Chronic couldn't work out #{expr.inspect}; please be more precise."
272
266
  end
273
-
267
+
274
268
  reference = args.first || Time.now
275
-
269
+
276
270
  if "as_of" == method
277
271
  between(time, reference)
278
272
  else
data/spec/by_star_spec.rb CHANGED
@@ -7,53 +7,58 @@ describe Post do
7
7
  # + 2 for today
8
8
  # + 2 for yesterday
9
9
  # + 2 for tomorrow
10
+ # + 1 for current week
10
11
  # + 1 for current weekend
11
12
  # + 1 for current fortnight
12
13
  # + 1 for the end of year
13
- # = 21
14
+ # = 22
14
15
  def this_years_posts
15
- 21
16
+ 22
16
17
  end
17
-
18
+
18
19
  def stub_time(day=1, month=1, year=Time.zone.now.year, hour=0, minute=0)
19
20
  stub = "#{day}-#{month}-#{year} #{hour}:#{minute}".to_time
20
21
  Time.stub!(:now).and_return(stub)
21
22
  Time.zone.stub!(:now).and_return(stub)
22
23
  end
23
-
24
+
24
25
  def range_test(&block)
25
26
  (1..31).to_a.each do |d|
26
27
  stub_time(d, 07, 2009, 05, 05)
27
28
  block.call
28
29
  end
29
30
  end
30
-
31
+
31
32
  def find(*args)
32
33
  method = description_args.first.sub(' ', '_')
33
34
  Post.send(method, *args)
34
35
  end
35
-
36
+
36
37
  def size(*args)
37
38
  method = description_args.first.sub(' ', '_')
38
39
  Post.send(method, *args).size
39
40
  end
40
-
41
+
41
42
  ["mysql", "sqlite3"].each do |adapter|
42
43
  ActiveRecord::Base.establish_connection(YAML::load_file(File.dirname(__FILE__) + "/database.yml")[adapter])
43
-
44
+
44
45
  describe "by year" do
45
46
  it "should be able to find all the posts in the current year" do
46
- size.should eql(this_years_posts.size)
47
+ size.should eql(this_years_posts)
47
48
  end
48
-
49
+
49
50
  it "should be able to find if given a string" do
50
- size(Time.zone.now.year.to_s).should eql(@this_years_post.size)
51
+ size(Time.zone.now.year.to_s).should eql(this_years_posts)
51
52
  end
52
-
53
+
53
54
  it "should be able to find a single post from last year" do
54
- size(Time.zone.now.year-1).should eql(1)
55
+ size(Time.zone.now.year-1).should eql(2)
55
56
  end
56
-
57
+
58
+ it "knows what last year's posts were" do
59
+ find(Time.zone.now.year-1).map(&:text).should eql(["Last year", "End of last year"])
60
+ end
61
+
57
62
  it "should error when given an invalid year" do
58
63
  # This is broken on 1.8.6 (and previous versions), any patchlevel after & before 111
59
64
  major, minor, trivial = RUBY_VERSION.split(".").map(&:to_i)
@@ -66,61 +71,68 @@ describe Post do
66
71
  find(2039).should be_empty
67
72
  end
68
73
  end
69
-
74
+
70
75
  it "should be able to use an alternative field (string)" do
71
76
  Event.by_year(nil, :field => "start_time").size.should eql(8)
72
77
  end
73
-
78
+
74
79
  it "should be able to use an alternative field (symbol)" do
75
80
  Event.by_year(nil, :field => :start_time).size.should eql(8)
76
81
  end
77
-
82
+
78
83
  it "should be able to use an alternative field (symbol) with directional searching" do
79
84
  stub_time
80
85
  Event.past(nil, :field => :start_time).size.should eql(1)
81
86
  end
82
-
87
+
83
88
  it "should be able to order the result set" do
84
89
  find(Time.zone.now.year, :order => "created_at DESC").first.text.should eql("That's it!")
85
90
  end
86
91
  end
87
-
92
+
88
93
  describe "by month" do
89
-
94
+
90
95
  it "should be able to find posts for the current month" do
91
96
  size.should eql(10)
92
97
  end
93
-
98
+
94
99
  it "should be able to find a single post for January" do
95
- size("January").should eql(10)
100
+ # If it is January we'll have all the "current" posts in there.
101
+ # This makes the count 10.
102
+ # I'm sure you can guess what happens when it's not January.
103
+ size("January").should eql(Time.now.month == 1 ? 10 : 1)
96
104
  end
97
-
105
+
98
106
  it "should be able to find two posts for the 2nd month" do
99
- # This test is fundamentally broken.
100
- # Sometimes the current month is #2, therefore this number is 10.
101
- # When it is not it is 2.
102
- size(2).should eql(2)
107
+ # If it is February we'll have all the "current" posts in there.
108
+ # This makes the count 10.
109
+ # I'm sure you can guess what happens when it's not February.
110
+ size(2).should eql(Time.now.month == 2 ? 10 : 1)
103
111
  end
104
-
112
+
105
113
  it "should be able to find three posts for the 3rd month, using time instance" do
106
- size(Time.local(Time.zone.now.year, 3, 1)).should eql(1)
114
+ # If it is March we'll have all the "current" posts in there.
115
+ # This makes the count 10.
116
+ # I'm sure you can guess what happens when it's not March.
117
+ time = Time.local(Time.zone.now.year, 3, 1)
118
+ size(time).should eql(Time.now.month == 3 ? 10 : 1)
107
119
  end
108
-
120
+
109
121
  it "should be able to find a single post from January last year" do
110
122
  size("January", :year => Time.zone.now.year - 1).should eql(1)
111
123
  end
112
-
124
+
113
125
  it "should fail when given incorrect months" do
114
126
  lambda { find(0) }.should raise_error(ByStar::ParseError)
115
127
  lambda { find(13) }.should raise_error(ByStar::ParseError)
116
128
  lambda { find("Ryan") }.should raise_error(ByStar::ParseError)
117
129
  lambda { find([1,2,3]) }.should raise_error(ByStar::ParseError)
118
130
  end
119
-
131
+
120
132
  it "should be able to take decimals" do
121
133
  size(1.5).should eql(1)
122
134
  end
123
-
135
+
124
136
  it "should be able to use an alternative field" do
125
137
  if Time.zone.now.month == 12
126
138
  Event.by_month(nil, :field => "start_time").size.should eql(4)
@@ -129,102 +141,107 @@ describe Post do
129
141
  Event.by_month(nil, :field => "start_time").size.should eql(1)
130
142
  end
131
143
  end
132
-
144
+
133
145
  it "should be able to specify the year as a string" do
134
146
  size(1, :year => (Time.zone.now.year - 1).to_s).should eql(1)
135
147
  end
136
-
148
+
137
149
  end
138
-
150
+
139
151
  describe "by fortnight" do
140
-
152
+
141
153
  it "should be able to find posts in the current fortnight" do
142
- stub_time
143
- size.should eql(4)
154
+ size.should eql(10)
144
155
  end
145
-
156
+
146
157
  it "should be able to find posts in the 1st fortnight" do
147
158
  size(0).should eql(2)
148
159
  end
149
-
160
+
150
161
  it "should be able to find posts for a fortnight ago" do
151
162
  stub_time
152
163
  size(2.weeks.ago).should eql(0)
153
164
  end
154
-
165
+
155
166
  it "should raise an error when given an invalid argument" do
156
167
  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.")
157
168
  end
158
-
169
+
159
170
  it "should be able to use an alternative field" do
160
171
  stub_time
161
172
  Event.by_fortnight(nil, :field => "start_time").size.should eql(0)
162
173
  end
163
174
  end
164
-
175
+
165
176
  describe "by week" do
166
-
177
+
167
178
  it "should be able to find posts in the current week" do
168
179
  stub_time
169
180
  size.should eql(2)
170
181
  end
171
-
182
+
172
183
  it "should be able to find posts in the 1st week" do
173
184
  size(0).should eql(1)
174
185
  end
175
-
186
+
176
187
  it "should be able to find posts in the 1st week of last year" do
177
188
  size(0, :year => Time.zone.now.year-1).should eql(1)
178
189
  end
179
-
190
+
180
191
  it "should not find any posts from a week ago" do
181
192
  stub_time
182
193
  size(1.week.ago).should eql(0)
183
194
  end
184
-
195
+
185
196
  it "should be able to find posts by a given date" do
186
197
  stub_time
187
198
  size(1.week.ago.to_date).should eql(0)
188
199
  end
189
-
200
+
190
201
  it "should find, not size the posts for the current week" do
191
202
  stub_time
192
203
  find.map(&:text).include?("The 'Current' Week")
193
204
  find.map(&:text).include?("Weekend of May")
194
205
  end
195
-
206
+
196
207
  it "should raise an error when given an invalid argument" do
197
208
  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.")
198
209
  end
199
-
210
+
200
211
  it "should be able to use an alternative field" do
201
212
  stub_time
202
213
  Event.by_week(nil, :field => "start_time").size.should eql(0)
203
214
  end
204
-
215
+
205
216
  it "should find posts at the start of the year" do
206
217
  size(0).should eql(1)
207
218
  end
208
-
219
+
209
220
  it "should find posts at the end of the year" do
210
221
  size(Time.zone.now.end_of_year).should eql(1)
211
222
  end
212
-
223
+
213
224
  end
214
-
225
+
215
226
  describe "by weekend" do
216
227
  it "should be able to find the posts on the weekend of the 1st of January" do
217
- stub_time
218
- size.should eql(1)
228
+ case Time.zone.now.wday
229
+ when 5 # Friday
230
+ size.should eql(3)
231
+ when 6 # Saturday
232
+ size.should eql(5)
233
+ else
234
+ size.should eql(3)
235
+ end
219
236
  end
220
-
237
+
221
238
  it "should be able to use an alternative field" do
222
239
  year = Time.zone.now.year
223
240
  stub_time(1, 8)
224
241
  Event.by_weekend(nil, :field => "start_time").size.should eql(0)
225
242
  end
226
243
  end
227
-
244
+
228
245
  describe "by current weekend" do
229
246
  it "should work" do
230
247
  range_test do
@@ -232,7 +249,7 @@ describe Post do
232
249
  end
233
250
  end
234
251
  end
235
-
252
+
236
253
  describe "by current work week" do
237
254
  it "should work" do
238
255
  range_test do
@@ -240,19 +257,18 @@ describe Post do
240
257
  end
241
258
  end
242
259
  end
243
-
260
+
244
261
  describe "by day" do
245
262
  it "should be able to find a post for today" do
246
263
  stub_time
247
- p Post.by_day
248
264
  size.should eql(1)
249
265
  end
250
-
266
+
251
267
  it "should be able to find a post by a given date" do
252
268
  stub_time
253
269
  size(Date.today).should eql(1)
254
270
  end
255
-
271
+
256
272
  it "should be able to use an alternative field" do
257
273
  Event.by_day(Time.now - 1.day, :field => "start_time").size.should eql(1)
258
274
  end
@@ -262,186 +278,186 @@ describe Post do
262
278
  it "should show the post for today" do
263
279
  find.map(&:text).should include("Today's post")
264
280
  end
265
-
281
+
266
282
  it "should be able to use an alternative field" do
267
283
  # Test may occur on an event day.
268
284
  stub_time
269
285
  Event.today(nil, :field => "start_time").size.should eql(0)
270
286
  end
271
-
287
+
272
288
  end
273
-
289
+
274
290
  describe "tomorrow" do
275
291
  it "should show the post for tomorrow" do
276
292
  find.map(&:text).should include("Tomorrow's post")
277
293
  end
278
294
  end
279
-
295
+
280
296
  describe "yesterday" do
281
297
  it "should show the post for yesterday" do
282
298
  find.map(&:text).should include("Yesterday's post")
283
299
  end
284
-
300
+
285
301
  it "should be able find yesterday, given a Date" do
286
302
  find(Time.now).map(&:text).should include("Yesterday's post")
287
303
  end
288
-
304
+
289
305
  it "should be able to use an alternative field" do
290
306
  # Test may occur on an event day.
291
307
  stub_time
292
308
  Event.yesterday(nil, :field => "start_time").size.should eql(0)
293
309
  end
294
-
310
+
295
311
  end
296
-
312
+
297
313
  describe "tomorrow" do
298
314
  it "should show the post for tomorrow" do
299
315
  find.map(&:text).should include("Tomorrow's post")
300
316
  end
301
-
317
+
302
318
  it "should be able find tomorrow, given a Date" do
303
319
  find(Time.now).map(&:text).should include("Tomorrow's post")
304
320
  end
305
-
321
+
306
322
  it "should be able to use an alternative field" do
307
323
  # Test may occur on an event day.
308
324
  stub_time
309
325
  Event.tomorrow(nil, :field => "start_time").size.should eql(0)
310
326
  end
311
327
  end
312
-
328
+
313
329
  describe "past" do
314
-
330
+
315
331
  before do
316
332
  stub_time
317
333
  end
318
-
334
+
319
335
  it "should show the correct number of posts in the past" do
320
336
  size.should eql(2)
321
337
  end
322
-
338
+
323
339
  it "should find for a given time" do
324
340
  size(Time.zone.now - 2.days).should eql(1)
325
341
  end
326
-
342
+
327
343
  it "should find for a given date" do
328
344
  size(Date.today - 2).should eql(1)
329
345
  end
330
-
346
+
331
347
  it "should find for a given string" do
332
348
  size("next tuesday").should eql(3)
333
349
  end
334
-
350
+
335
351
  it "should be able to find all events before Ryan's birthday using a non-standard field" do
336
352
  Event.past("01-01-#{Time.zone.now.year+2}".to_time, :field => "start_time").size.should eql(9)
337
353
  end
338
-
354
+
339
355
  it "should be able to order the find" do
340
356
  stub_time(2,1)
341
357
  find(Date.today, :order => "created_at ASC").first.text.should eql("Last year")
342
358
  find(Date.today, :order => "created_at DESC").first.text.should eql("post 1")
343
359
  end
344
-
360
+
345
361
  end
346
-
362
+
347
363
  describe "future" do
348
364
  before do
349
365
  stub_time
350
366
  end
351
-
367
+
352
368
  it "should show the correct number of posts in the future" do
353
369
  size.should eql(21)
354
370
  end
355
-
371
+
356
372
  it "should find for a given date" do
357
373
  size(Date.today - 2).should eql(23)
358
374
  end
359
-
375
+
360
376
  it "should find for a given string" do
361
377
  size("next tuesday").should eql(21)
362
378
  end
363
-
379
+
364
380
  it "should be able to find all events before Dad's birthday using a non-standard field" do
365
381
  # TODO: This will change in May. Figure out how to fix.
366
382
  Event.past("05-07-#{Time.zone.now.year}".to_time, :field => "start_time").size.should eql(5)
367
383
  end
368
384
  end
369
-
385
+
370
386
  describe "as of" do
371
387
  it "should be able to find posts as of 2 weeks ago" do
372
388
  stub_time
373
389
  Post.as_of_2_weeks_ago.size.should eql(2)
374
390
  end
375
-
391
+
376
392
  it "should be able to find posts as of 2 weeks before a given time" do
377
393
  stub_time
378
394
  Post.as_of_2_weeks_ago(Time.zone.now + 1.month).size.should eql(3)
379
395
  end
380
-
396
+
381
397
  it "should error if given a date in the past far enough back" do
382
398
  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.")
383
399
  end
384
-
400
+
385
401
  it "should not do anything if given an invalid date" do
386
402
  lambda { Post.as_of_ryans_birthday }.should raise_error(ByStar::ParseError, "Chronic couldn't work out \"Ryans birthday\"; please be more precise.")
387
403
  end
388
404
  end
389
-
405
+
390
406
  describe "between" do
391
407
  it "should find posts between last tuesday and next tuesday" do
392
408
  stub_time
393
409
  size("last tuesday", "next tuesday").should eql(2)
394
410
  end
395
-
411
+
396
412
  it "should find between two times" do
397
413
  stub_time
398
414
  size(Time.zone.now - 5.days, Time.zone.now + 5.days).should eql(2)
399
415
  end
400
-
416
+
401
417
  it "should find between two dates" do
402
418
  stub_time
403
419
  size(Date.today, Date.today + 5).should eql(1)
404
420
  end
405
421
  end
406
-
422
+
407
423
  describe "up to" do
408
424
  it "should be able to find posts up to 6 weeks from now" do
409
425
  stub_time
410
426
  Post.up_to_6_weeks_from_now.size.should eql(2)
411
427
  end
412
-
428
+
413
429
  it "should be able to find posts up to 6 weeks from a given time" do
414
430
  stub_time
415
431
  Post.up_to_6_weeks_from_now(Time.zone.now - 1.month).size.should eql(3)
416
432
  end
417
-
433
+
418
434
  it "should error if given a date in the past" do
419
435
  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.")
420
436
  end
421
-
437
+
422
438
  it "should not do anything if given an invalid date" do
423
439
  lambda { Post.up_to_ryans_birthday }.should raise_error(ByStar::ParseError, "Chronic couldn't work out \"Ryans birthday\"; please be more precise.")
424
440
  end
425
-
441
+
426
442
  end
427
-
443
+
428
444
  # Because we override method_missing, we ensure that it still works as it should with this test.
429
445
  describe "method_missing" do
430
446
  it "should still work" do
431
447
  Post.find_by_text("Today's post").should_not be_nil
432
448
  end
433
-
449
+
434
450
  it "should raise a proper NoMethodError" do
435
451
  lambda { Post.idontexist }.should raise_error(NoMethodError, %r(^undefined method `idontexist'))
436
452
  end
437
453
  end
438
-
454
+
439
455
  describe "named_scopes" do
440
456
  it "should be compatible" do
441
457
  Event.secret.by_year(nil, :field => "start_time").size.should eql(1)
442
458
  end
443
459
  end
444
-
460
+
445
461
  describe "joins" do
446
462
  it "should not have ambiguous column names" do
447
463
  lambda { Post.by_month do
@@ -449,10 +465,10 @@ describe Post do
449
465
  end }.should_not raise_error
450
466
  end
451
467
  end
452
-
453
-
468
+
469
+
454
470
  describe "nested find" do
455
-
471
+
456
472
  it "should be able to find posts after right now" do
457
473
  stub_time
458
474
  # The post at the end of last year
@@ -463,85 +479,87 @@ describe Post do
463
479
  { :conditions => ["created_at > ?", Time.now] }
464
480
  end.size.should eql(0)
465
481
  end
466
-
482
+
467
483
  it "should be able to find a single post from last year with the tag 'ruby'" do
468
484
  Post.by_year(Time.zone.now.year - 1) do
469
485
  { :include => :tags, :conditions => ["tags.name = ?", 'ruby'] }
470
486
  end.size.should eql(1)
471
487
  end
472
-
488
+
473
489
  it "should be able to find a single post from January last year with the tag 'ruby'" do
474
490
  Post.by_month("January", :year => Time.zone.now.year - 1) do
475
491
  { :include => :tags, :conditions => ["tags.name = ?", 'ruby'] }
476
492
  end.size.should eql(1)
477
493
  end
478
-
494
+
479
495
  it "should be able to find a single post from the current fortnight with the tag 'fortnight'" do
480
496
  Post.by_fortnight do
481
497
  { :include => :tags, :conditions => ["tags.name = ?", 'fortnight'] }
482
498
  end.size.should eql(1)
483
499
  end
484
-
500
+
485
501
  it "should be able to find a single post from the current week with the tag 'week'" do
486
502
  Post.by_week do
487
503
  { :include => :tags, :conditions => ["tags.name = ?", 'week'] }
488
504
  end.size.should eql(1)
489
505
  end
490
-
506
+
491
507
  it "should be able to find a single pot from the last week of last year with the tag 'final'" do
492
508
  Post.by_week(52, :year => Time.zone.now.year - 1) do
493
509
  { :include => :tags, :conditions => ["tags.name = ?", 'final'] }
494
510
  end.size.should eql(1)
495
511
  end
496
-
512
+
497
513
  it "should be able to find a single post from the current weekend with the tag 'weekend'" do
498
514
  Post.by_weekend do
499
515
  { :include => :tags, :conditions => ["tags.name = ?", 'weekend'] }
500
516
  end.size.should eql(1)
501
517
  end
502
-
518
+
503
519
  it "should be able to find a single post from the current day with the tag 'today'" do
504
520
  Post.by_day do
505
521
  { :include => :tags, :conditions => ["tags.name = ?", 'today'] }
506
522
  end.size.should eql(1)
507
523
  end
508
-
524
+
509
525
  it "should be able to find a single post from yesterday with the tag 'yesterday'" do
510
526
  Post.yesterday do
511
527
  { :include => :tags, :conditions => ["tags.name = ?", 'yesterday'] }
512
528
  end.size.should eql(1)
513
529
  end
514
-
515
-
530
+
531
+
516
532
  it "should be able to find a single post from tomorrow with the tag 'tomorrow'" do
517
533
  Post.tomorrow do
518
534
  { :include => :tags, :conditions => ["tags.name = ?", 'tomorrow'] }
519
535
  end.size.should eql(1)
520
536
  end
521
-
537
+
522
538
  it "should be able to find a single post from the past with the tag 'yesterday'" do
523
539
  Post.past do
524
540
  { :include => :tags, :conditions => ["tags.name = ?", 'yesterday'] }
525
541
  end.size.should eql(1)
526
542
  end
527
-
543
+
528
544
  it "should be able to find a single post from the future with the tag 'tomorrow'" do
529
545
  Post.future do
530
546
  { :include => :tags, :conditions => ["tags.name = ?", 'tomorrow'] }
531
547
  end.size.should eql(1)
532
548
  end
533
-
549
+
534
550
  it "should work when block is empty" do
535
- stub_time
536
- Post.future { }.size.should eql(this_years_posts)
551
+ stub_time
552
+ # This will not find the post on the 1st January.
553
+ # future uses > rather than >=.
554
+ Post.future { }.size.should eql(this_years_posts - 1)
537
555
  end
538
-
556
+
539
557
  it "should be able to find a single post from the future with the tag 'tomorrow' (redux)" do
540
558
  Post.future(Time.zone.now, :include => :tags, :conditions => ["tags.name = ?", 'tomorrow']).size.should eql(1)
541
559
  end
542
-
560
+
543
561
  end
544
-
562
+
545
563
  describe "Calculations" do
546
564
  describe "Sum" do
547
565
  describe "by year" do
@@ -553,7 +571,7 @@ describe Post do
553
571
  Invoice.sum_by_year(:value).should eql(135500)
554
572
  end
555
573
  end
556
-
574
+
557
575
  describe "by month" do
558
576
  it "current month" do
559
577
  stub_time
@@ -561,7 +579,7 @@ describe Post do
561
579
  Invoice.sum_by_month(:value).should eql(15500)
562
580
  end
563
581
  end
564
-
582
+
565
583
  describe "by day" do
566
584
  it "current day" do
567
585
  stub_time(2, 1) # 2nd January
@@ -569,24 +587,24 @@ describe Post do
569
587
  end
570
588
  end
571
589
  end
572
-
590
+
573
591
  describe "Count" do
574
592
  describe "by year" do
575
593
  it "current year" do
576
594
  # 13 invoices, 1 for every month + 1 for this month.
577
595
  Invoice.count_by_year.should eql(14)
578
596
  end
579
-
597
+
580
598
  it "using a field" do
581
599
  # 12 invoices, as we have a single invoice without a number.
582
600
  Invoice.count_by_year(:number).should eql(Invoice.by_year.size-1)
583
601
  end
584
-
602
+
585
603
  it "different year" do
586
604
  # 1 invoice from last year
587
605
  Invoice.count_by_year(:all, Time.zone.now.year-1).should eql(1)
588
606
  end
589
-
607
+
590
608
  it "current year with the given tag" do
591
609
  # BROKEN: Due to time range looking up from beginning of current year to end of next
592
610
  Post.count_by_year do
@@ -594,27 +612,27 @@ describe Post do
594
612
  end.should eql(1)
595
613
  end
596
614
  end
597
-
615
+
598
616
  describe "by month" do
599
617
  it "current month" do
600
618
  Invoice.count_by_month
601
619
  end
602
-
620
+
603
621
  it "using a field" do
604
622
  Invoice.count_by_month(:number).should eql(Invoice.by_month.size-1)
605
623
  end
606
-
624
+
607
625
  it "different month" do
608
626
  stub_time
609
627
  Invoice.count_by_month(:all, 9)
610
628
  end
611
-
629
+
612
630
  it "current month with the given tag" do
613
631
  Post.count_by_month(:all, Time.zone.now) do
614
632
  { :include => :tags, :conditions => ["tags.name = ?", 'tomorrow'] }
615
633
  end.should eql(1)
616
634
  end
617
-
635
+
618
636
  it "current month with blank block" do
619
637
  Post.count_by_month(:all, Time.zone.now) { }.should eql(10)
620
638
  end
@@ -623,6 +641,19 @@ describe Post do
623
641
 
624
642
  end
625
643
 
644
+ describe "chaining of methods" do
645
+ # a by_star and a by_direction method, in that order
646
+ it "should be able to chain today and past" do
647
+ Post.today.past.size.should eql(4)
648
+ end
649
+
650
+ # a by_direction and by_star method, in that order
651
+ it "should be able to chain together past and today" do
652
+ Post.past.today.size.should eql(4)
653
+ end
654
+
655
+ end
656
+
626
657
  describe "edge cases" do
627
658
  # This method previously generated sql like: `day_entries`.`spent_at`.`spent_at`.`spent_at`.`spent_at`
628
659
  # Which is *obviously* incorrect and #omg worthy.
@@ -630,14 +661,14 @@ describe Post do
630
661
  Invoice.first.day_entries.between((Time.zone.now - 3.days).to_date, Time.zone.now.to_date, :field => "spent_at")
631
662
  end
632
663
  end
633
-
664
+
634
665
  describe Time do
635
666
  it "should work out the beginning of a weekend (Friday 3pm)" do
636
667
  range_test do
637
668
  Time.now.beginning_of_weekend.strftime("%A %I:%M%p").should eql("Friday 03:00PM")
638
669
  end
639
670
  end
640
-
671
+
641
672
  it "should work out the end of a weekend (Monday 3am)" do
642
673
  range_test do
643
674
  Time.now.end_of_weekend.strftime("%A %I:%M%p").should eql("Monday 03:00AM")
@@ -645,5 +676,5 @@ describe Post do
645
676
  end
646
677
  end
647
678
  end
648
-
679
+
649
680
  end