by_star 2.2.0.rc1 → 2.2.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.
data/UPGRADING CHANGED
@@ -1,9 +1,11 @@
1
1
  Upgrading to ByStar 2.2.0
2
2
  -------------------------
3
3
 
4
- * For Mongoid only, ByStar's `.between` method has been removed and replaced with `.between_times`
5
- (previously `.between_times` was an alias to `.between`). Mongoid already provides a native `.between`
6
- finder method that we do not want to mask. ActiveRecord users may continue to use either method.
4
+ * ActiveRecord: the `between` method has been deprecated as of version 2.2.0, and will be removed in version 3.3.0.
5
+ Please use `between_times` instead.
6
+
7
+ * Mongoid: the `between` method has been removed as of version 2.2.0, as it conflicts with the native Mongoid `between`
8
+ method. Please use `between_times` instead.
7
9
 
8
10
  * Chronic gem (used for time string parsing) has been removed as a hard dependency for ByStar,
9
11
  however it is still supported. If you would like to use Chronic with ByStar, please explicitly
@@ -5,10 +5,12 @@ module ByStar
5
5
  include ByStar::Between
6
6
  include ByStar::Directional
7
7
 
8
- def by_star_field(start_field = nil, end_field = nil, options = {})
9
- @by_star_start_field ||= start_field
10
- @by_star_end_field ||= end_field
8
+ def by_star_field(*args)
9
+ options = args.extract_options!
10
+ @by_star_start_field ||= args[0]
11
+ @by_star_end_field ||= args[1]
11
12
  @by_star_offset ||= options[:offset]
13
+ @by_star_scope ||= options[:scope]
12
14
  end
13
15
 
14
16
  def by_star_offset(options = {})
@@ -31,6 +33,19 @@ module ByStar
31
33
  field.to_s
32
34
  end
33
35
 
36
+ def by_star_scope(options={})
37
+ scope = options[:scope] || @by_star_scope || self
38
+ if scope.is_a?(Proc)
39
+ if scope.arity == 0
40
+ return instance_exec(&scope)
41
+ else
42
+ return instance_exec(self, &scope)
43
+ end
44
+ else
45
+ return scope
46
+ end
47
+ end
48
+
34
49
  protected
35
50
 
36
51
  # Wrapper function which extracts time and options for each by_star query.
@@ -14,18 +14,6 @@ module ByStar
14
14
  end
15
15
  end
16
16
 
17
- def today(options={})
18
- by_day(Time.zone.now, options)
19
- end
20
-
21
- def yesterday(options={})
22
- by_day(Time.zone.now.yesterday, options)
23
- end
24
-
25
- def tomorrow(options={})
26
- by_day(Time.zone.now.tomorrow, options)
27
- end
28
-
29
17
  def by_week(*args)
30
18
  with_by_star_options(*args) do |time, options|
31
19
  time = ByStar::Normalization.week(time, options)
@@ -76,5 +64,57 @@ module ByStar
76
64
  between_times(time.beginning_of_year, time.end_of_year, options)
77
65
  end
78
66
  end
67
+
68
+ def today(options={})
69
+ by_day(Time.zone.now, options)
70
+ end
71
+
72
+ def yesterday(options={})
73
+ by_day(Time.zone.now.yesterday, options)
74
+ end
75
+
76
+ def tomorrow(options={})
77
+ by_day(Time.zone.now.tomorrow, options)
78
+ end
79
+
80
+ def past_day(options={})
81
+ between_times(Time.zone.now - 1.day, Time.zone.now, options)
82
+ end
83
+
84
+ def past_week(options={})
85
+ between_times(Time.zone.now - 1.week, Time.zone.now, options)
86
+ end
87
+
88
+ def past_fortnight(options={})
89
+ between_times(Time.zone.now - 2.weeks, Time.zone.now, options)
90
+ end
91
+
92
+ def past_month(options={})
93
+ between_times(Time.zone.now - 1.month, Time.zone.now, options)
94
+ end
95
+
96
+ def past_year(options={})
97
+ between_times(Time.zone.now - 1.year, Time.zone.now, options)
98
+ end
99
+
100
+ def next_day(options={})
101
+ between_times(Time.zone.now, Time.zone.now + 1.day, options)
102
+ end
103
+
104
+ def next_week(options={})
105
+ between_times(Time.zone.now, Time.zone.now + 1.week, options)
106
+ end
107
+
108
+ def next_fortnight(options={})
109
+ between_times(Time.zone.now, Time.zone.now + 2.weeks, options)
110
+ end
111
+
112
+ def next_month(options={})
113
+ between_times(Time.zone.now, Time.zone.now + 1.month, options)
114
+ end
115
+
116
+ def next_year(options={})
117
+ between_times(Time.zone.now, Time.zone.now + 1.year, options)
118
+ end
79
119
  end
80
120
  end
@@ -18,14 +18,14 @@ module ByStar
18
18
  # A "Fortnight" is defined as a two week period, with the first fortnight of the
19
19
  # year beginning on 1st January.
20
20
  def beginning_of_fortnight
21
- beginning_of_year + ((self - beginning_of_year) / 2.weeks).to_i * 2.weeks
21
+ (beginning_of_year.to_date + 14 * ((self - beginning_of_year) / 2.weeks).to_i).beginning_of_day
22
22
  end
23
23
 
24
24
  def end_of_fortnight
25
- (beginning_of_fortnight + 13.days).end_of_day
25
+ (beginning_of_fortnight.to_date + 13).end_of_day
26
26
  end
27
27
 
28
- # A "Calendar Month" is defined as a month as it appears on a calendar, including days
28
+ # A "Calendar Month" is defined as a month as it appears on a calendar, including days form
29
29
  # previous/following months which are part of the first/last weeks of the given month.
30
30
  def beginning_of_calendar_month(*args)
31
31
  beginning_of_month.beginning_of_week(*args)
@@ -9,16 +9,23 @@ module ByStar
9
9
  #
10
10
  # Currently only supports Time objects.
11
11
  def between_times_query(start, finish, options={})
12
- scope = if options[:strict] || by_star_start_field == by_star_end_field
13
- where("#{by_star_start_field} >= ? AND #{by_star_end_field} <= ?", start, finish)
12
+ start_field = by_star_start_field(options)
13
+ end_field = by_star_end_field(options)
14
+
15
+ scope = by_star_scope(options)
16
+ scope = if options[:strict] || start_field == end_field
17
+ scope.where("#{start_field} >= ? AND #{end_field} <= ?", start, finish)
14
18
  else
15
- where("#{by_star_end_field} > ? AND #{by_star_start_field} < ?", start, finish)
19
+ scope.where("#{end_field} > ? AND #{start_field} < ?", start, finish)
16
20
  end
17
21
  scope = scope.order(options[:order]) if options[:order]
18
22
  scope
19
23
  end
20
24
 
21
- alias_method :between, :between_times
25
+ def between(*args)
26
+ ActiveSupport::Deprecation.warn 'ByStar `between` method will be removed in v3.0.0. Please use `between_times`'
27
+ between_times(*args)
28
+ end
22
29
 
23
30
  protected
24
31
 
@@ -27,26 +34,26 @@ module ByStar
27
34
  end
28
35
 
29
36
  def before_query(time, options={})
30
- field = by_star_start_field
31
- where("#{field} <= ?", time)
37
+ field = by_star_start_field(options)
38
+ by_star_scope(options).where("#{field} <= ?", time)
32
39
  end
33
40
 
34
41
  def after_query(time, options={})
35
- field = by_star_start_field
36
- where("#{field} >= ?", time)
42
+ field = by_star_start_field(options)
43
+ by_star_scope(options).where("#{field} >= ?", time)
37
44
  end
38
45
  end
39
46
 
40
47
  def previous(options={})
41
48
  field = self.class.by_star_start_field
42
49
  value = self.send(field.split(".").last)
43
- self.class.where("#{field} < ?", value).reorder("#{field} DESC").first
50
+ self.class.by_star_scope(options).where("#{field} < ?", value).reorder("#{field} DESC").first
44
51
  end
45
52
 
46
53
  def next(options={})
47
54
  field = self.class.by_star_start_field
48
55
  value = self.send(field.split(".").last)
49
- self.class.where("#{field} > ?", value).reorder("#{field} ASC").first
56
+ self.class.by_star_scope(options).where("#{field} > ?", value).reorder("#{field} ASC").first
50
57
  end
51
58
  end
52
59
  end
@@ -10,10 +10,14 @@ module Mongoid
10
10
  include ::ByStar::Base
11
11
 
12
12
  def between_times_query(start, finish, options={})
13
- scope = if options[:strict] || by_star_start_field == by_star_end_field
14
- gte(by_star_start_field => start).lte(by_star_end_field => finish)
13
+ start_field = by_star_start_field(options)
14
+ end_field = by_star_end_field(options)
15
+
16
+ scope = by_star_scope(options)
17
+ scope = if options[:strict] || start_field == end_field
18
+ scope.gte(start_field => start).lte(end_field => finish)
15
19
  else
16
- gt(by_star_end_field => start).lt(by_star_start_field => finish)
20
+ scope.gt(end_field => start).lt(start_field => finish)
17
21
  end
18
22
  scope = scope.order_by(field => options[:order]) if options[:order]
19
23
  scope
@@ -36,24 +40,24 @@ module Mongoid
36
40
  end
37
41
 
38
42
  def before_query(time, options={})
39
- field = by_star_start_field
40
- lte(field => time)
43
+ field = by_star_start_field(options)
44
+ by_star_scope(options).lte(field => time)
41
45
  end
42
46
 
43
47
  def after_query(time, options={})
44
- field = by_star_start_field
45
- gte(field => time)
48
+ field = by_star_start_field(options)
49
+ by_star_scope(options).gte(field => time)
46
50
  end
47
51
  end
48
52
 
49
53
  def previous(options={})
50
54
  field = self.class.by_star_start_field
51
- self.class.lt(field => self.send(field)).desc(field).first
55
+ self.class.by_star_scope(options).lt(field => self.send(field)).desc(field).first
52
56
  end
53
57
 
54
58
  def next(options={})
55
59
  field = self.class.by_star_start_field
56
- self.class.gt(field => self.send(field)).asc(field).first
60
+ self.class.by_star_scope(options).gt(field => self.send(field)).asc(field).first
57
61
  end
58
62
  end
59
63
  end
@@ -1,3 +1,3 @@
1
1
  module ByStar
2
- VERSION = '2.2.0.rc1'
2
+ VERSION = '2.2.0'
3
3
  end
@@ -1,6 +1,10 @@
1
1
  class Post < ActiveRecord::Base
2
2
  end
3
3
 
4
+ class Appointment < ActiveRecord::Base
5
+ by_star_field scope: ->{ where(day_of_month: 1) }
6
+ end
7
+
4
8
  class Event < ActiveRecord::Base
5
9
  by_star_field :start_time, :end_time, offset: 3.hours
6
10
  end
@@ -3,9 +3,17 @@ ActiveRecord::Schema.define do
3
3
 
4
4
  create_table :posts, :force => true do |t|
5
5
  t.timestamps
6
+ t.integer :day_of_month
6
7
  end
7
8
 
8
9
  create_table :events, :force => true do |t|
10
+ t.timestamps
9
11
  t.datetime :start_time, :end_time
12
+ t.integer :day_of_month
13
+ end
14
+
15
+ create_table :appointments, :force => true do |t|
16
+ t.timestamps
17
+ t.integer :day_of_month
10
18
  end
11
19
  end
@@ -2,14 +2,28 @@ class Post
2
2
  include Mongoid::Document
3
3
  include Mongoid::Timestamps
4
4
  include Mongoid::ByStar
5
+
6
+ field :day_of_month, type: Integer
7
+ end
8
+
9
+ class Appointment
10
+ include Mongoid::Document
11
+ include Mongoid::Timestamps
12
+ include Mongoid::ByStar
13
+
14
+ field :day_of_month, type: Integer
15
+
16
+ by_star_field scope: ->{ where(day_of_month: 1) }
5
17
  end
6
18
 
7
19
  class Event
8
20
  include Mongoid::Document
21
+ include Mongoid::Timestamps
9
22
  include Mongoid::ByStar
10
23
 
11
24
  field :st, as: :start_time, type: Time
12
25
  field :end_time, type: Time
26
+ field :day_of_month, type: Integer
13
27
 
14
28
  by_star_field :start_time, :end_time, offset: 3.hours
15
29
  end
@@ -1,4 +1,13 @@
1
- %w(2013-12-31
1
+ %w(2013-11-01
2
+ 2013-11-30
3
+ 2013-12-01
4
+ 2013-12-05
5
+ 2013-12-08
6
+ 2013-12-16
7
+ 2013-12-22
8
+ 2013-12-25
9
+ 2013-12-28
10
+ 2013-12-31
2
11
  2014-01-01
3
12
  2014-01-01
4
13
  2014-01-05
@@ -11,6 +20,7 @@
11
20
  2014-03-15
12
21
  2014-04-01
13
22
  2014-04-15).map{|d| Time.zone.parse(d) + 17.hours }.each do |d|
14
- Post.create!(:created_at => d)
15
- Event.create!(:start_time => d - 5.days, :end_time => d + 5.days)
23
+ Post.create!(:created_at => d, day_of_month: d.day)
24
+ Appointment.create!(:created_at => d, day_of_month: d.day)
25
+ Event.create!(:created_at => d, :start_time => d - 5.days, :end_time => d + 5.days, day_of_month: d.day)
16
26
  end
@@ -4,6 +4,7 @@ Dir[File.dirname(__FILE__) + '/../shared/*.rb'].each {|file| require file }
4
4
  describe ActiveRecord do
5
5
  before(:all) do
6
6
  ActiveRecord::Base.default_timezone = :utc
7
+ # ActiveRecord::Base.logger = Logger.new(STDOUT)
7
8
 
8
9
  db_config = YAML::load_file(File.dirname(__FILE__) + '/../../database.yml')
9
10
  if db_config.has_key?('sqlite') && db_config['sqlite'].has_key?('database')
@@ -28,7 +29,9 @@ describe ActiveRecord do
28
29
  it_behaves_like 'by week'
29
30
  it_behaves_like 'by weekend'
30
31
  it_behaves_like 'by year'
32
+ it_behaves_like 'relative'
31
33
  it_behaves_like 'offset parameter'
34
+ it_behaves_like 'scope parameter'
32
35
 
33
36
  it 'should be able to order the result set' do
34
37
  scope = Post.by_year(Time.zone.now.year, :order => 'created_at DESC')
@@ -5,6 +5,7 @@ describe 'Mongoid' do
5
5
 
6
6
  before(:all) do
7
7
  DATABASE_NAME = "mongoid_#{Process.pid}"
8
+ # Moped.logger = Logger.new(STDOUT)
8
9
 
9
10
  Mongoid.configure do |config|
10
11
  config.connect_to DATABASE_NAME
@@ -27,7 +28,9 @@ describe 'Mongoid' do
27
28
  it_behaves_like 'by week'
28
29
  it_behaves_like 'by weekend'
29
30
  it_behaves_like 'by year'
31
+ it_behaves_like 'relative'
30
32
  it_behaves_like 'offset parameter'
33
+ it_behaves_like 'scope parameter'
31
34
 
32
35
  describe '#between_times' do
33
36
  subject { Post.between_times(Time.parse('2014-01-01'), Time.parse('2014-01-06')) }
@@ -11,7 +11,7 @@ shared_examples_for 'by calendar month' do
11
11
 
12
12
  context 'timespan' do
13
13
  subject { Event.by_calendar_month(1) }
14
- its(:count){ should eq 8 }
14
+ its(:count){ should eq 10 }
15
15
  end
16
16
 
17
17
  context 'timespan strict' do
@@ -23,17 +23,17 @@ shared_examples_for 'by calendar month' do
23
23
 
24
24
  context 'point-in-time' do
25
25
  subject { Post.by_calendar_month(12, year: 2013) }
26
- its(:count){ should eq 4 }
26
+ its(:count){ should eq 12 }
27
27
  end
28
28
 
29
29
  context 'timespan' do
30
30
  subject { Event.by_calendar_month('December', year: 2013) }
31
- its(:count){ should eq 5 }
31
+ its(:count){ should eq 13 }
32
32
  end
33
33
 
34
34
  context 'timespan strict' do
35
35
  subject { Event.by_calendar_month('Dec', year: 2013, strict: true) }
36
- its(:count){ should eq 1 }
36
+ its(:count){ should eq 9 }
37
37
  end
38
38
  end
39
39
 
@@ -44,7 +44,7 @@ shared_examples_for 'by calendar month' do
44
44
  end
45
45
 
46
46
  it 'should be able to use an alternative field' do
47
- Event.by_calendar_month(:field => 'end_time').count.should eq 8
47
+ Event.by_calendar_month(:field => 'end_time').count.should eq 9
48
48
  end
49
49
 
50
50
  context ':start_day option' do
@@ -11,7 +11,7 @@ shared_examples_for 'by day' do
11
11
 
12
12
  context 'timespan' do
13
13
  subject { Event.by_day(Time.parse '2014-01-01') }
14
- its(:count){ should eq 4 }
14
+ its(:count){ should eq 5 }
15
15
  end
16
16
 
17
17
  context 'timespan strict' do
@@ -20,7 +20,7 @@ shared_examples_for 'by day' do
20
20
  end
21
21
 
22
22
  it 'should be able to use an alternative field' do
23
- Event.by_day(:field => 'end_time').count.should eq 4
23
+ Event.by_day(:field => 'end_time').count.should eq 0
24
24
  end
25
25
 
26
26
  it 'should support :offset option' do
@@ -37,13 +37,21 @@ shared_examples_for 'by day' do
37
37
 
38
38
  context 'timespan' do
39
39
  subject { Event.today }
40
- its(:count){ should eq 4 }
40
+ its(:count){ should eq 5 }
41
41
  end
42
42
 
43
43
  context 'timespan strict' do
44
44
  subject { Event.today(strict: true) }
45
45
  its(:count){ should eq 0 }
46
46
  end
47
+
48
+ it 'should be able to use an alternative field' do
49
+ Event.today(:field => 'created_at').count.should eq 2
50
+ end
51
+
52
+ it 'should support :offset option' do
53
+ Post.today(:offset => -24.hours).count.should eq 1
54
+ end
47
55
  end
48
56
 
49
57
  describe '#yesterday' do # 2013-12-31
@@ -55,13 +63,21 @@ shared_examples_for 'by day' do
55
63
 
56
64
  context 'timespan' do
57
65
  subject { Event.yesterday }
58
- its(:count){ should eq 4 }
66
+ its(:count){ should eq 5 }
59
67
  end
60
68
 
61
69
  context 'timespan strict' do
62
70
  subject { Event.yesterday(strict: true) }
63
71
  its(:count){ should eq 0 }
64
72
  end
73
+
74
+ it 'should be able to use an alternative field' do
75
+ Event.yesterday(:field => 'created_at').count.should eq 1
76
+ end
77
+
78
+ it 'should support :offset option' do
79
+ Post.yesterday(:offset => 24.hours).count.should eq 2
80
+ end
65
81
  end
66
82
 
67
83
  describe '#tomorrow' do # 2014-01-02
@@ -73,12 +89,20 @@ shared_examples_for 'by day' do
73
89
 
74
90
  context 'timespan' do
75
91
  subject { Event.tomorrow }
76
- its(:count){ should eq 4 }
92
+ its(:count){ should eq 5 }
77
93
  end
78
94
 
79
95
  context 'timespan strict' do
80
96
  subject { Event.tomorrow(strict: true) }
81
97
  its(:count){ should eq 0 }
82
98
  end
99
+
100
+ it 'should be able to use an alternative field' do
101
+ Event.tomorrow(:field => 'created_at').count.should eq 0
102
+ end
103
+
104
+ it 'should support :offset option' do
105
+ Post.tomorrow(:offset => -24.hours).count.should eq 2
106
+ end
83
107
  end
84
108
  end