by_star 3.0.0 → 4.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/mysql.yml +92 -0
- data/.github/workflows/postgresql.yml +99 -0
- data/.gitignore +1 -0
- data/.travis.yml +67 -36
- data/CHANGELOG.md +15 -0
- data/README.md +172 -133
- data/UPGRADING +1 -3
- data/by_star.gemspec +2 -2
- data/lib/by_star/base.rb +16 -15
- data/lib/by_star/between.rb +81 -52
- data/lib/by_star/directional.rb +2 -4
- data/lib/by_star/kernel/date.rb +0 -9
- data/lib/by_star/kernel/in_time_zone.rb +20 -0
- data/lib/by_star/normalization.rb +52 -23
- data/lib/by_star/orm/active_record/by_star.rb +20 -6
- data/lib/by_star/orm/mongoid/by_star.rb +20 -6
- data/lib/by_star/version.rb +1 -1
- data/lib/by_star.rb +1 -0
- data/spec/database.yml +1 -1
- data/spec/fixtures/active_record/models.rb +2 -2
- data/spec/fixtures/mongoid/models.rb +1 -1
- data/spec/fixtures/shared/seeds.rb +10 -0
- data/spec/gemfiles/Gemfile.rails +5 -0
- data/spec/gemfiles/Gemfile.rails32 +7 -0
- data/spec/gemfiles/Gemfile.rails40 +1 -1
- data/spec/gemfiles/Gemfile.rails41 +1 -1
- data/spec/gemfiles/Gemfile.rails42 +2 -2
- data/spec/gemfiles/Gemfile.rails50 +1 -4
- data/spec/gemfiles/Gemfile.rails51 +1 -4
- data/spec/gemfiles/Gemfile.rails52 +7 -0
- data/spec/gemfiles/Gemfile.rails60 +7 -0
- data/spec/gemfiles/Gemfile.rails61 +7 -0
- data/spec/integration/active_record/active_record_spec.rb +6 -3
- data/spec/integration/mongoid/mongoid_spec.rb +3 -1
- data/spec/integration/shared/at_time.rb +53 -0
- data/spec/integration/shared/between_dates.rb +99 -0
- data/spec/integration/shared/between_times.rb +27 -10
- data/spec/integration/shared/by_day.rb +24 -0
- data/spec/integration/shared/by_direction.rb +11 -57
- data/spec/integration/shared/index_scope_parameter.rb +111 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/unit/kernel_date_spec.rb +6 -6
- data/spec/unit/normalization_spec.rb +128 -49
- metadata +33 -21
- data/spec/gemfiles/Gemfile.master +0 -6
- data/spec/integration/shared/scope_parameter.rb +0 -73
data/lib/by_star/base.rb
CHANGED
@@ -11,6 +11,7 @@ module ByStar
|
|
11
11
|
@by_star_end_field ||= args[1]
|
12
12
|
@by_star_offset ||= options[:offset]
|
13
13
|
@by_star_scope ||= options[:scope]
|
14
|
+
@by_star_index_scope ||= options[:index_scope]
|
14
15
|
end
|
15
16
|
|
16
17
|
def by_star_offset(options = {})
|
@@ -33,21 +34,6 @@ module ByStar
|
|
33
34
|
field.to_s
|
34
35
|
end
|
35
36
|
|
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
|
-
elsif options[:scope_args]
|
42
|
-
return instance_exec(*Array(options[:scope_args]), &scope)
|
43
|
-
else
|
44
|
-
raise 'ByStar :scope Proc requires :scope_args to be specified.'
|
45
|
-
end
|
46
|
-
else
|
47
|
-
return scope
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
37
|
protected
|
52
38
|
|
53
39
|
# Wrapper function which extracts time and options for each by_star query.
|
@@ -64,5 +50,20 @@ module ByStar
|
|
64
50
|
time = args.first || Time.zone.now
|
65
51
|
block.call(time, options)
|
66
52
|
end
|
53
|
+
|
54
|
+
def by_star_eval_index_scope(start_time, end_time, options)
|
55
|
+
value = options[:index_scope] || @by_star_index_scope
|
56
|
+
value = value.call(start_time, end_time, options) if value.is_a?(Proc)
|
57
|
+
case value
|
58
|
+
when nil, false then nil
|
59
|
+
when Time, DateTime, Date then value.in_time_zone
|
60
|
+
when ActiveSupport::Duration then start_time - value
|
61
|
+
when Numeric then start_time - value.seconds
|
62
|
+
when :beginning_of_day
|
63
|
+
offset = options[:offset] || 0
|
64
|
+
(start_time - offset).beginning_of_day + offset
|
65
|
+
else raise 'ByStar :index_scope option value is not a supported type.'
|
66
|
+
end
|
67
|
+
end
|
67
68
|
end
|
68
69
|
end
|
data/lib/by_star/between.rb
CHANGED
@@ -5,19 +5,25 @@ module ByStar
|
|
5
5
|
def between_times(*args)
|
6
6
|
options = args.extract_options!.symbolize_keys!
|
7
7
|
|
8
|
-
start_time, end_time =
|
9
|
-
|
10
|
-
else args[0..1]
|
11
|
-
end
|
8
|
+
start_time, end_time = ByStar::Normalization.extract_range(args)
|
9
|
+
offset = options[:offset] || 0
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
if start_time.is_a?(Date)
|
12
|
+
start_time = ByStar::Normalization.apply_offset_start(start_time.in_time_zone, offset)
|
13
|
+
elsif start_time
|
14
|
+
start_time += offset.seconds
|
15
|
+
end
|
16
|
+
|
17
|
+
if end_time.is_a?(Date)
|
18
|
+
end_time = ByStar::Normalization.apply_offset_end(end_time.in_time_zone, offset)
|
19
|
+
elsif end_time
|
20
|
+
end_time += offset.seconds
|
21
|
+
end
|
16
22
|
|
17
23
|
start_field = by_star_start_field(options)
|
18
24
|
end_field = by_star_end_field(options)
|
19
|
-
scope = by_star_scope(options)
|
20
25
|
|
26
|
+
scope = self
|
21
27
|
scope = if !start_time && !end_time
|
22
28
|
scope # do nothing
|
23
29
|
elsif !end_time
|
@@ -29,26 +35,49 @@ module ByStar
|
|
29
35
|
elsif options[:strict]
|
30
36
|
by_star_span_strict_query(scope, start_field, end_field, start_time, end_time)
|
31
37
|
else
|
32
|
-
|
38
|
+
by_star_span_loose_query(scope, start_field, end_field, start_time, end_time, options)
|
33
39
|
end
|
34
40
|
|
35
41
|
scope = by_star_order(scope, options[:order]) if options[:order]
|
36
|
-
|
37
42
|
scope
|
38
43
|
end
|
39
44
|
|
45
|
+
def between_dates(*args)
|
46
|
+
options = args.extract_options!
|
47
|
+
start_date, end_date = ByStar::Normalization.extract_range(args)
|
48
|
+
start_date = ByStar::Normalization.date(start_date)
|
49
|
+
end_date = ByStar::Normalization.date(end_date)
|
50
|
+
between_times(start_date, end_date, options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def at_time(*args)
|
54
|
+
with_by_star_options(*args) do |time, options|
|
55
|
+
start_field = by_star_start_field(options)
|
56
|
+
end_field = by_star_end_field(options)
|
57
|
+
|
58
|
+
scope = self
|
59
|
+
scope = if start_field == end_field
|
60
|
+
by_star_point_overlap_query(scope, start_field, time)
|
61
|
+
else
|
62
|
+
by_star_span_overlap_query(scope, start_field, end_field, time, options)
|
63
|
+
end
|
64
|
+
scope = by_star_order(scope, options[:order]) if options[:order]
|
65
|
+
scope
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
40
69
|
def by_day(*args)
|
41
70
|
with_by_star_options(*args) do |time, options|
|
42
|
-
|
43
|
-
|
71
|
+
date = ByStar::Normalization.date(time)
|
72
|
+
between_dates(date, date, options)
|
44
73
|
end
|
45
74
|
end
|
46
75
|
|
47
76
|
def by_week(*args)
|
48
77
|
with_by_star_options(*args) do |time, options|
|
49
|
-
|
78
|
+
date = ByStar::Normalization.week(time, options)
|
50
79
|
start_day = Array(options[:start_day])
|
51
|
-
|
80
|
+
between_dates(date.beginning_of_week(*start_day), date.end_of_week(*start_day), options)
|
52
81
|
end
|
53
82
|
end
|
54
83
|
|
@@ -60,97 +89,97 @@ module ByStar
|
|
60
89
|
|
61
90
|
def by_weekend(*args)
|
62
91
|
with_by_star_options(*args) do |time, options|
|
63
|
-
|
64
|
-
|
92
|
+
date = ByStar::Normalization.week(time, options)
|
93
|
+
between_dates(date.beginning_of_weekend, date.end_of_weekend, options)
|
65
94
|
end
|
66
95
|
end
|
67
96
|
|
68
97
|
def by_fortnight(*args)
|
69
98
|
with_by_star_options(*args) do |time, options|
|
70
|
-
|
71
|
-
|
99
|
+
date = ByStar::Normalization.fortnight(time, options)
|
100
|
+
between_dates(date.beginning_of_fortnight, date.end_of_fortnight, options)
|
72
101
|
end
|
73
102
|
end
|
74
103
|
|
75
104
|
def by_month(*args)
|
76
105
|
with_by_star_options(*args) do |time, options|
|
77
|
-
|
78
|
-
|
106
|
+
date = ByStar::Normalization.month(time, options)
|
107
|
+
between_dates(date.beginning_of_month, date.end_of_month, options)
|
79
108
|
end
|
80
109
|
end
|
81
110
|
|
82
111
|
def by_calendar_month(*args)
|
83
112
|
with_by_star_options(*args) do |time, options|
|
84
|
-
|
113
|
+
date = ByStar::Normalization.month(time, options)
|
85
114
|
start_day = Array(options[:start_day])
|
86
|
-
|
115
|
+
between_dates(date.beginning_of_calendar_month(*start_day), date.end_of_calendar_month(*start_day), options)
|
87
116
|
end
|
88
117
|
end
|
89
118
|
|
90
119
|
def by_quarter(*args)
|
91
120
|
with_by_star_options(*args) do |time, options|
|
92
|
-
|
93
|
-
|
121
|
+
date = ByStar::Normalization.quarter(time, options)
|
122
|
+
between_dates(date.beginning_of_quarter, date.end_of_quarter, options)
|
94
123
|
end
|
95
124
|
end
|
96
125
|
|
97
126
|
def by_year(*args)
|
98
127
|
with_by_star_options(*args) do |time, options|
|
99
|
-
|
100
|
-
|
128
|
+
date = ByStar::Normalization.year(time, options)
|
129
|
+
between_dates(date.beginning_of_year, date.to_date.end_of_year, options)
|
101
130
|
end
|
102
131
|
end
|
103
132
|
|
104
|
-
def today(options={})
|
105
|
-
by_day(
|
133
|
+
def today(options = {})
|
134
|
+
by_day(Date.current, options)
|
106
135
|
end
|
107
136
|
|
108
|
-
def yesterday(options={})
|
109
|
-
by_day(
|
137
|
+
def yesterday(options = {})
|
138
|
+
by_day(Date.yesterday, options)
|
110
139
|
end
|
111
140
|
|
112
|
-
def tomorrow(options={})
|
113
|
-
by_day(
|
141
|
+
def tomorrow(options = {})
|
142
|
+
by_day(Date.tomorrow, options)
|
114
143
|
end
|
115
144
|
|
116
|
-
def past_day(options={})
|
117
|
-
between_times(Time.
|
145
|
+
def past_day(options = {})
|
146
|
+
between_times(Time.current - 1.day, Time.current, options)
|
118
147
|
end
|
119
148
|
|
120
|
-
def past_week(options={})
|
121
|
-
between_times(Time.
|
149
|
+
def past_week(options = {})
|
150
|
+
between_times(Time.current - 1.week, Time.current, options)
|
122
151
|
end
|
123
152
|
|
124
|
-
def past_fortnight(options={})
|
125
|
-
between_times(Time.
|
153
|
+
def past_fortnight(options = {})
|
154
|
+
between_times(Time.current - 2.weeks, Time.current, options)
|
126
155
|
end
|
127
156
|
|
128
|
-
def past_month(options={})
|
129
|
-
between_times(Time.
|
157
|
+
def past_month(options = {})
|
158
|
+
between_times(Time.current - 1.month, Time.current, options)
|
130
159
|
end
|
131
160
|
|
132
|
-
def past_year(options={})
|
133
|
-
between_times(Time.
|
161
|
+
def past_year(options = {})
|
162
|
+
between_times(Time.current - 1.year, Time.current, options)
|
134
163
|
end
|
135
164
|
|
136
|
-
def next_day(options={})
|
137
|
-
between_times(Time.
|
165
|
+
def next_day(options = {})
|
166
|
+
between_times(Time.current, Time.current + 1.day, options)
|
138
167
|
end
|
139
168
|
|
140
|
-
def next_week(options={})
|
141
|
-
between_times(Time.
|
169
|
+
def next_week(options = {})
|
170
|
+
between_times(Time.current, Time.current + 1.week, options)
|
142
171
|
end
|
143
172
|
|
144
|
-
def next_fortnight(options={})
|
145
|
-
between_times(Time.
|
173
|
+
def next_fortnight(options = {})
|
174
|
+
between_times(Time.current, Time.current + 2.weeks, options)
|
146
175
|
end
|
147
176
|
|
148
|
-
def next_month(options={})
|
149
|
-
between_times(Time.
|
177
|
+
def next_month(options = {})
|
178
|
+
between_times(Time.current, Time.current + 1.month, options)
|
150
179
|
end
|
151
180
|
|
152
|
-
def next_year(options={})
|
153
|
-
between_times(Time.
|
181
|
+
def next_year(options = {})
|
182
|
+
between_times(Time.current, Time.current + 1.year, options)
|
154
183
|
end
|
155
184
|
end
|
156
185
|
end
|
data/lib/by_star/directional.rb
CHANGED
@@ -4,20 +4,18 @@ module ByStar
|
|
4
4
|
|
5
5
|
def before(*args)
|
6
6
|
with_by_star_options(*args) do |time, options|
|
7
|
-
scope = by_star_scope(options)
|
8
7
|
field = by_star_start_field(options)
|
9
8
|
time = ByStar::Normalization.time(time)
|
10
|
-
by_star_before_query(
|
9
|
+
by_star_before_query(self, field, time)
|
11
10
|
end
|
12
11
|
end
|
13
12
|
alias_method :before_now, :before
|
14
13
|
|
15
14
|
def after(*args)
|
16
15
|
with_by_star_options(*args) do |time, options|
|
17
|
-
scope = by_star_scope(options)
|
18
16
|
field = by_star_start_field(options)
|
19
17
|
time = ByStar::Normalization.time(time)
|
20
|
-
by_star_after_query(
|
18
|
+
by_star_after_query(self, field, time)
|
21
19
|
end
|
22
20
|
end
|
23
21
|
alias_method :after_now, :after
|
data/lib/by_star/kernel/date.rb
CHANGED
@@ -3,15 +3,6 @@ module ByStar
|
|
3
3
|
module Kernel
|
4
4
|
|
5
5
|
module Date
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
|
10
|
-
# Shim to alias Rails 3 #to_time_in_current_zone to Rails 4 name #in_time_zone
|
11
|
-
if method_defined?(:to_time_in_current_zone) && !method_defined?(:in_time_zone)
|
12
|
-
alias_method :in_time_zone, :to_time_in_current_zone
|
13
|
-
end
|
14
|
-
end
|
15
6
|
|
16
7
|
# A "Weekend" is defined as beginning of Saturday to end of Sunday.
|
17
8
|
# The weekend for a given date will be the the next weekend if the day Mon-Thurs,
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ByStar
|
2
|
+
|
3
|
+
module Kernel
|
4
|
+
|
5
|
+
module InTimeZone
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
if method_defined?(:to_time_in_current_zone) && !method_defined?(:in_time_zone)
|
10
|
+
alias_method :in_time_zone, :to_time_in_current_zone
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
::Date.__send__(:include, ByStar::Kernel::InTimeZone)
|
18
|
+
::Time.__send__(:include, ByStar::Kernel::InTimeZone)
|
19
|
+
::DateTime.__send__(:include, ByStar::Kernel::InTimeZone)
|
20
|
+
::ActiveSupport::TimeWithZone.__send__(:include, ByStar::Kernel::InTimeZone)
|
@@ -6,33 +6,22 @@ module ByStar
|
|
6
6
|
|
7
7
|
class << self
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
when Date then value.in_time_zone
|
14
|
-
else value
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def time_string(value)
|
19
|
-
defined?(Chronic) ? time_string_chronic(value) : time_string_fallback(value)
|
9
|
+
def date(value)
|
10
|
+
value = parse_time(value) if value.is_a?(String)
|
11
|
+
value = value.try(:in_time_zone) unless value.is_a?(Date)
|
12
|
+
value.try(:to_date)
|
20
13
|
end
|
21
14
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
def time_string_fallback(value)
|
28
|
-
Time.zone.parse(value) || raise(ByStar::ParseError, "Cannot parse String #{value.inspect}")
|
15
|
+
def time(value)
|
16
|
+
value = parse_time(value) if value.is_a?(String)
|
17
|
+
value.try(:in_time_zone)
|
29
18
|
end
|
30
19
|
|
31
20
|
def week(value, options={})
|
32
21
|
value = try_string_to_int(value)
|
33
22
|
case value
|
34
23
|
when Integer then week_integer(value, options)
|
35
|
-
else
|
24
|
+
else date(value)
|
36
25
|
end
|
37
26
|
end
|
38
27
|
|
@@ -55,7 +44,7 @@ module ByStar
|
|
55
44
|
value = try_string_to_int(value)
|
56
45
|
case value
|
57
46
|
when Integer then fortnight_integer(value, options)
|
58
|
-
else
|
47
|
+
else date(value)
|
59
48
|
end
|
60
49
|
end
|
61
50
|
|
@@ -69,7 +58,7 @@ module ByStar
|
|
69
58
|
value = try_string_to_int(value)
|
70
59
|
case value
|
71
60
|
when Integer then quarter_integer(value, options)
|
72
|
-
else
|
61
|
+
else date(value)
|
73
62
|
end
|
74
63
|
end
|
75
64
|
|
@@ -83,7 +72,7 @@ module ByStar
|
|
83
72
|
value = try_string_to_int(value)
|
84
73
|
case value
|
85
74
|
when Integer, String then month_integer(value, options)
|
86
|
-
else
|
75
|
+
else date(value)
|
87
76
|
end
|
88
77
|
end
|
89
78
|
|
@@ -98,7 +87,7 @@ module ByStar
|
|
98
87
|
value = try_string_to_int(value)
|
99
88
|
case value
|
100
89
|
when Integer then year_integer(value)
|
101
|
-
else
|
90
|
+
else date(value)
|
102
91
|
end
|
103
92
|
end
|
104
93
|
|
@@ -122,6 +111,46 @@ module ByStar
|
|
122
111
|
rescue
|
123
112
|
value
|
124
113
|
end
|
114
|
+
|
115
|
+
def time_in_units(seconds)
|
116
|
+
days = seconds / 1.day
|
117
|
+
time = Time.at(seconds).utc
|
118
|
+
{ days: days, hour: time.hour, min: time.min, sec: time.sec }
|
119
|
+
end
|
120
|
+
|
121
|
+
def apply_offset_start(time, offset)
|
122
|
+
units = time_in_units(offset)
|
123
|
+
time += units.delete(:days).days
|
124
|
+
time.change(units)
|
125
|
+
end
|
126
|
+
|
127
|
+
def apply_offset_end(time, offset)
|
128
|
+
units = time_in_units(offset)
|
129
|
+
time += units.delete(:days).days
|
130
|
+
(time + 1.day).change(units) - 1.second
|
131
|
+
end
|
132
|
+
|
133
|
+
def extract_range(args)
|
134
|
+
case args[0]
|
135
|
+
when Array, Range then [args[0].first, args[0].last]
|
136
|
+
else args[0..1]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def parse_time(value)
|
143
|
+
defined?(Chronic) ? parse_time_chronic(value) : parse_time_fallback(value)
|
144
|
+
end
|
145
|
+
|
146
|
+
def parse_time_chronic(value)
|
147
|
+
Chronic.time_class = Time.zone
|
148
|
+
Chronic.parse(value) || raise(ByStar::ParseError, "Chronic could not parse String #{value.inspect}")
|
149
|
+
end
|
150
|
+
|
151
|
+
def parse_time_fallback(value)
|
152
|
+
Time.zone.parse(value) || raise(ByStar::ParseError, "Cannot parse String #{value.inspect}")
|
153
|
+
end
|
125
154
|
end
|
126
155
|
end
|
127
156
|
end
|
@@ -19,8 +19,22 @@ module ByStar
|
|
19
19
|
scope.where("#{start_field} >= ? AND #{start_field} <= ? AND #{end_field} >= ? AND #{end_field} <= ?", start_time, end_time, start_time, end_time)
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
22
|
+
def by_star_span_loose_query(scope, start_field, end_field, start_time, end_time, options)
|
23
|
+
index_scope = by_star_eval_index_scope(start_time, end_time, options)
|
24
|
+
scope = scope.where("#{end_field} > ? AND #{start_field} < ?", start_time, end_time)
|
25
|
+
scope = scope.where("#{start_field} >= ?", index_scope) if index_scope
|
26
|
+
scope
|
27
|
+
end
|
28
|
+
|
29
|
+
def by_star_point_overlap_query(scope, field, time)
|
30
|
+
scope.where("#{field} = ?", time)
|
31
|
+
end
|
32
|
+
|
33
|
+
def by_star_span_overlap_query(scope, start_field, end_field, time, options)
|
34
|
+
index_scope = by_star_eval_index_scope(time, time, options)
|
35
|
+
scope = scope.where("#{end_field} > ? AND #{start_field} <= ?", time, time)
|
36
|
+
scope = scope.where("#{start_field} >= ?", index_scope) if index_scope
|
37
|
+
scope
|
24
38
|
end
|
25
39
|
|
26
40
|
def by_star_before_query(scope, field, time)
|
@@ -37,25 +51,25 @@ module ByStar
|
|
37
51
|
|
38
52
|
def oldest_query(options={})
|
39
53
|
field = by_star_start_field(options)
|
40
|
-
|
54
|
+
reorder("#{field} ASC").first
|
41
55
|
end
|
42
56
|
|
43
57
|
def newest_query(options={})
|
44
58
|
field = by_star_start_field(options)
|
45
|
-
|
59
|
+
reorder("#{field} DESC").first
|
46
60
|
end
|
47
61
|
end
|
48
62
|
|
49
63
|
def previous(options={})
|
50
64
|
field = self.class.by_star_start_field(options)
|
51
65
|
value = self.send(field.split(".").last)
|
52
|
-
self.class.
|
66
|
+
self.class.where("#{field} < ?", value).reorder("#{field} DESC").first
|
53
67
|
end
|
54
68
|
|
55
69
|
def next(options={})
|
56
70
|
field = self.class.by_star_start_field(options)
|
57
71
|
value = self.send(field.split(".").last)
|
58
|
-
self.class.
|
72
|
+
self.class.where("#{field} > ?", value).reorder("#{field} ASC").first
|
59
73
|
end
|
60
74
|
end
|
61
75
|
end
|
@@ -36,8 +36,22 @@ module Mongoid
|
|
36
36
|
scope.where(start_field => range).where(end_field => range)
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
|
39
|
+
def by_star_span_loose_query(scope, start_field, end_field, start_time, end_time, options)
|
40
|
+
index_scope = by_star_eval_index_scope(start_time, end_time, options)
|
41
|
+
scope = scope.gt(end_field => start_time).lt(start_field => end_time)
|
42
|
+
scope = scope.gte(start_field => index_scope) if index_scope
|
43
|
+
scope
|
44
|
+
end
|
45
|
+
|
46
|
+
def by_star_point_overlap_query(scope, field, time)
|
47
|
+
scope.where(field => time)
|
48
|
+
end
|
49
|
+
|
50
|
+
def by_star_span_overlap_query(scope, start_field, end_field, time, options)
|
51
|
+
index_scope = by_star_eval_index_scope(time, time, options)
|
52
|
+
scope = scope.gt(end_field => time).lte(start_field => time)
|
53
|
+
scope = scope.gte(start_field => index_scope) if index_scope
|
54
|
+
scope
|
41
55
|
end
|
42
56
|
|
43
57
|
def by_star_before_query(scope, field, time)
|
@@ -54,23 +68,23 @@ module Mongoid
|
|
54
68
|
|
55
69
|
def oldest_query(options={})
|
56
70
|
field = by_star_start_field(options)
|
57
|
-
|
71
|
+
all.reorder(field => :asc).first
|
58
72
|
end
|
59
73
|
|
60
74
|
def newest_query(options={})
|
61
75
|
field = by_star_start_field(options)
|
62
|
-
|
76
|
+
all.reorder(field => :desc).first
|
63
77
|
end
|
64
78
|
end
|
65
79
|
|
66
80
|
def previous(options={})
|
67
81
|
field = self.class.by_star_start_field(options)
|
68
|
-
self.class.
|
82
|
+
self.class.lt(field => self.send(field)).reorder(field => :desc).first
|
69
83
|
end
|
70
84
|
|
71
85
|
def next(options={})
|
72
86
|
field = self.class.by_star_start_field(options)
|
73
|
-
self.class.
|
87
|
+
self.class.gt(field => self.send(field)).reorder(field => :asc).first
|
74
88
|
end
|
75
89
|
end
|
76
90
|
end
|
data/lib/by_star/version.rb
CHANGED
data/lib/by_star.rb
CHANGED
data/spec/database.yml
CHANGED
@@ -2,11 +2,11 @@ class Post < ActiveRecord::Base
|
|
2
2
|
end
|
3
3
|
|
4
4
|
class Appointment < ActiveRecord::Base
|
5
|
-
by_star_field
|
5
|
+
by_star_field index_scope: ->(start){ start - 5.days }
|
6
6
|
end
|
7
7
|
|
8
8
|
class Event < ActiveRecord::Base
|
9
9
|
by_star_field :start_time, :end_time, offset: 3.hours
|
10
10
|
|
11
|
-
default_scope ->{ order(day_of_month
|
11
|
+
default_scope ->{ order('day_of_month ASC') }
|
12
12
|
end
|
@@ -24,3 +24,13 @@
|
|
24
24
|
Appointment.create!(created_at: d, day_of_month: d.day)
|
25
25
|
Event.create!(created_at: d, start_time: d - 5.days, end_time: d + 5.days, day_of_month: d.day)
|
26
26
|
end
|
27
|
+
|
28
|
+
# Sydney timezone specific records
|
29
|
+
%w(
|
30
|
+
2020-04-05
|
31
|
+
2020-10-04
|
32
|
+
).map{|d| Date.parse(d) }.each do |d|
|
33
|
+
[1, 4, 5, 10].each do |h|
|
34
|
+
Event.create!(start_time: d + h.hour, end_time: d + h.hour + 30.minutes, created_at: Date.parse('2011-01-01').in_time_zone)
|
35
|
+
end
|
36
|
+
end
|