by_star 0.6.3 → 0.6.4

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