by_star 2.2.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.gitignore +5 -5
- data/.travis.yml +61 -35
- data/CHANGELOG.md +44 -35
- data/Gemfile +18 -25
- data/MIT-LICENSE +20 -20
- data/README.md +577 -540
- data/Rakefile +18 -18
- data/UPGRADING +6 -12
- data/by_star.gemspec +34 -32
- data/cleaner.rb +24 -24
- data/lib/by_star.rb +17 -16
- data/lib/by_star/base.rb +68 -70
- data/lib/by_star/between.rb +156 -120
- data/lib/by_star/directional.rb +37 -33
- data/lib/by_star/kernel/date.rb +50 -19
- data/lib/by_star/kernel/time.rb +41 -41
- data/lib/by_star/normalization.rb +127 -118
- data/lib/by_star/orm/active_record/by_star.rb +61 -69
- data/lib/by_star/orm/mongoid/by_star.rb +76 -73
- data/lib/by_star/orm/mongoid/reorder.rb +23 -0
- data/lib/by_star/version.rb +3 -3
- data/spec/database.yml +15 -15
- data/spec/fixtures/active_record/models.rb +12 -10
- data/spec/fixtures/active_record/schema.rb +19 -19
- data/spec/fixtures/mongoid/models.rb +31 -29
- data/spec/fixtures/shared/seeds.rb +26 -26
- data/spec/gemfiles/Gemfile.master +6 -0
- data/spec/gemfiles/Gemfile.rails40 +7 -0
- data/spec/gemfiles/Gemfile.rails41 +7 -0
- data/spec/gemfiles/Gemfile.rails42 +7 -0
- data/spec/gemfiles/Gemfile.rails50 +10 -0
- data/spec/gemfiles/Gemfile.rails51 +10 -0
- data/spec/integration/active_record/active_record_spec.rb +38 -53
- data/spec/integration/mongoid/mongoid_spec.rb +37 -46
- data/spec/integration/shared/between_times.rb +82 -0
- data/spec/integration/shared/by_calendar_month.rb +55 -55
- data/spec/integration/shared/by_cweek.rb +54 -0
- data/spec/integration/shared/by_day.rb +96 -108
- data/spec/integration/shared/by_direction.rb +172 -153
- data/spec/integration/shared/by_fortnight.rb +48 -48
- data/spec/integration/shared/by_month.rb +50 -50
- data/spec/integration/shared/by_quarter.rb +49 -49
- data/spec/integration/shared/by_week.rb +54 -54
- data/spec/integration/shared/by_weekend.rb +49 -49
- data/spec/integration/shared/by_year.rb +48 -48
- data/spec/integration/shared/offset_parameter.rb +32 -31
- data/spec/integration/shared/order_parameter.rb +36 -0
- data/spec/integration/shared/relative.rb +174 -174
- data/spec/integration/shared/scope_parameter.rb +73 -72
- data/spec/spec_helper.rb +29 -29
- data/spec/unit/kernel_date_spec.rb +113 -60
- data/spec/unit/kernel_time_spec.rb +57 -57
- data/spec/unit/normalization_spec.rb +305 -255
- metadata +61 -62
@@ -1,72 +1,73 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
shared_examples_for 'scope parameter' do
|
4
|
-
|
5
|
-
describe 'scope' do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'scope parameter' do
|
4
|
+
|
5
|
+
describe ':scope' do
|
6
|
+
|
7
|
+
it 'should memoize the scope variable' do
|
8
|
+
expect(Event.instance_variable_get(:@by_star_scope)).to be_nil
|
9
|
+
expect(Post.instance_variable_get(:@by_star_scope)).to be_nil
|
10
|
+
expect(Appointment.instance_variable_get(:@by_star_scope)).to be_a Proc
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'between_times with default scope' do
|
14
|
+
subject { Appointment.between_times(Date.parse('2013-12-01'), Date.parse('2014-02-01')) }
|
15
|
+
it { expect(subject.count).to eql(3) }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'between_times with scope override as a query criteria' do
|
19
|
+
subject { Appointment.between_times(Date.parse('2013-12-01')..Date.parse('2014-02-01'), scope: Appointment.unscoped) }
|
20
|
+
it { expect(subject.count).to eql(14) }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'between_times with scope override as a Lambda' do
|
24
|
+
subject { Appointment.between_times([Date.parse('2013-12-01'), Date.parse('2014-02-01')], scope: ->{ unscoped }) }
|
25
|
+
it { expect(subject.count).to eql(14) }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'between_times with scope override as a Lambda' do
|
29
|
+
subject { Appointment.between_times(Date.parse('2013-12-01')..Date.parse('2014-02-01'), scope: ->(x){ unscoped }) }
|
30
|
+
it{ expect{ subject }.to raise_error(RuntimeError, 'ByStar :scope Proc requires :scope_args to be specified.') }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'between_times with scope override as a Proc with arguments' do
|
34
|
+
subject { Appointment.between_times(Date.parse('2013-12-01'), Date.parse('2014-02-01'), scope: Proc.new{ unscoped }) }
|
35
|
+
it { expect(subject.count).to eql(14) }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'between_times with scope override as a Proc with arguments' do
|
39
|
+
subject { Appointment.between_times([Date.parse('2013-12-01'), Date.parse('2014-02-01')], scope: Proc.new{|x,y| unscoped }) }
|
40
|
+
it{ expect{ subject }.to raise_error(RuntimeError, 'ByStar :scope Proc requires :scope_args to be specified.') }
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'by_month with default scope' do
|
44
|
+
subject { Appointment.by_month(Date.parse('2014-01-01')) }
|
45
|
+
it { expect(subject.count).to eql(2) }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'by_month with scope override as a query criteria' do
|
49
|
+
subject { Appointment.by_month(Date.parse('2014-01-01'), scope: Appointment.unscoped) }
|
50
|
+
it { expect(subject.count).to eql(6) }
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'by_month with scope override as a Lambda' do
|
54
|
+
subject { Appointment.by_month(Date.parse('2014-01-01'), scope: ->{ unscoped }) }
|
55
|
+
it { expect(subject.count).to eql(6) }
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'by_month with scope override as a Lambda with arguments' do
|
59
|
+
subject { Appointment.by_month(Date.parse('2014-01-01'), scope: ->(x){ unscoped }) }
|
60
|
+
it{ expect{ subject }.to raise_error(RuntimeError, 'ByStar :scope Proc requires :scope_args to be specified.') }
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'by_month with scope override as a Proc' do
|
64
|
+
subject { Appointment.by_month(Date.parse('2014-01-01'), scope: Proc.new{ unscoped }) }
|
65
|
+
it { expect(subject.count).to eql(6) }
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'by_month with scope override as a Proc with arguments' do
|
69
|
+
subject { Appointment.by_month(Date.parse('2014-01-01'), scope: Proc.new{|x| unscoped }) }
|
70
|
+
it{ expect{ subject }.to raise_error(RuntimeError, 'ByStar :scope Proc requires :scope_args to be specified.') }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
Bundler.setup
|
4
|
-
require 'fileutils'
|
5
|
-
require 'logger'
|
6
|
-
|
7
|
-
FileUtils.mkdir_p(File.dirname(__FILE__) + "/tmp")
|
8
|
-
$:.unshift(File.join(File.dirname(__FILE__), "../lib"))
|
9
|
-
|
10
|
-
require 'active_record'
|
11
|
-
require 'mongoid'
|
12
|
-
require 'chronic'
|
13
|
-
require 'timecop'
|
14
|
-
require 'by_star'
|
15
|
-
|
16
|
-
# Specs should pass regardless of timezone
|
17
|
-
Time.zone = %w(Asia/Tokyo America/New_York Australia/Sydney UTC).sample
|
18
|
-
puts "Running specs in #{Time.zone} timezone..."
|
19
|
-
|
20
|
-
# Set Rails time to 2014-01-01 00:00:00
|
21
|
-
Timecop.travel(Time.zone.local(2014))
|
22
|
-
|
23
|
-
def testing_mongoid?
|
24
|
-
ENV['DB'] == 'mongodb'
|
25
|
-
end
|
26
|
-
|
27
|
-
def testing_active_record?
|
28
|
-
|
29
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
require 'fileutils'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
FileUtils.mkdir_p(File.dirname(__FILE__) + "/tmp")
|
8
|
+
$:.unshift(File.join(File.dirname(__FILE__), "../lib"))
|
9
|
+
|
10
|
+
require 'active_record'
|
11
|
+
require 'mongoid'
|
12
|
+
require 'chronic'
|
13
|
+
require 'timecop'
|
14
|
+
require 'by_star'
|
15
|
+
|
16
|
+
# Specs should pass regardless of timezone
|
17
|
+
Time.zone = %w(Asia/Tokyo America/New_York Australia/Sydney UTC).sample
|
18
|
+
puts "Running specs in #{Time.zone} timezone..."
|
19
|
+
|
20
|
+
# Set Rails time to 2014-01-01 00:00:00
|
21
|
+
Timecop.travel(Time.zone.local(2014))
|
22
|
+
|
23
|
+
def testing_mongoid?
|
24
|
+
ENV['DB'] == 'mongodb'
|
25
|
+
end
|
26
|
+
|
27
|
+
def testing_active_record?
|
28
|
+
!testing_mongoid?
|
29
|
+
end
|
@@ -1,60 +1,113 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Date do
|
4
|
-
|
5
|
-
describe '#in_time_zone' do
|
6
|
-
|
7
|
-
subject { Date.new }
|
8
|
-
|
9
|
-
before do
|
10
|
-
stub_const('Date', Class.new)
|
11
|
-
Date.
|
12
|
-
end
|
13
|
-
|
14
|
-
context 'when #in_time_zone is already defined' do
|
15
|
-
before do
|
16
|
-
Date.
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'when ByStar::Kernel::Date included' do
|
20
|
-
before do
|
21
|
-
::Date.__send__(:include, ByStar::Kernel::Date)
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'should not be aliased to #to_time_in_current_zone' do
|
25
|
-
subject.
|
26
|
-
subject.in_time_zone
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'when ByStar::Kernel::Date not included' do
|
31
|
-
|
32
|
-
it 'should not be aliased to #to_time_in_current_zone' do
|
33
|
-
subject.
|
34
|
-
subject.in_time_zone
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context 'when #in_time_zone is not defined' do
|
40
|
-
|
41
|
-
context 'when ByStar::Kernel::Date included' do
|
42
|
-
before do
|
43
|
-
::Date.__send__(:include, ByStar::Kernel::Date)
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should be aliased to #to_time_in_current_zone' do
|
47
|
-
subject.
|
48
|
-
subject.in_time_zone
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'when ByStar::Kernel::Date not included' do
|
53
|
-
|
54
|
-
it 'should raise NoMethodError' do
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Date do
|
4
|
+
|
5
|
+
describe '#in_time_zone' do
|
6
|
+
|
7
|
+
subject { Date.new }
|
8
|
+
|
9
|
+
before do
|
10
|
+
stub_const('Date', Class.new)
|
11
|
+
allow_any_instance_of(Date).to receive(:to_time_in_current_zone)
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when #in_time_zone is already defined' do
|
15
|
+
before do
|
16
|
+
expect_any_instance_of(Date).to receive(:in_time_zone)
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when ByStar::Kernel::Date included' do
|
20
|
+
before do
|
21
|
+
::Date.__send__(:include, ByStar::Kernel::Date)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not be aliased to #to_time_in_current_zone' do
|
25
|
+
expect(subject).not_to receive(:to_time_in_current_zone)
|
26
|
+
subject.in_time_zone
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when ByStar::Kernel::Date not included' do
|
31
|
+
|
32
|
+
it 'should not be aliased to #to_time_in_current_zone' do
|
33
|
+
expect(subject).not_to receive(:to_time_in_current_zone)
|
34
|
+
subject.in_time_zone
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when #in_time_zone is not defined' do
|
40
|
+
|
41
|
+
context 'when ByStar::Kernel::Date included' do
|
42
|
+
before do
|
43
|
+
::Date.__send__(:include, ByStar::Kernel::Date)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should be aliased to #to_time_in_current_zone' do
|
47
|
+
expect(subject).to receive(:to_time_in_current_zone)
|
48
|
+
subject.in_time_zone
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when ByStar::Kernel::Date not included' do
|
53
|
+
|
54
|
+
it 'should raise NoMethodError' do
|
55
|
+
expect{ subject.in_time_zone }.to raise_error(NoMethodError)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'weekend' do
|
62
|
+
|
63
|
+
(0..6).each do |n|
|
64
|
+
context "Monday plus #{n} days" do
|
65
|
+
subject { Date.parse('2014-01-06') + n.days }
|
66
|
+
it { expect(subject.beginning_of_weekend).to eq Date.parse('2014-01-11') }
|
67
|
+
it { expect(subject.end_of_weekend).to eq Date.parse('2014-01-12') }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'fortnight' do
|
73
|
+
|
74
|
+
context 'first day of year' do
|
75
|
+
subject { Date.parse '2014-01-01' }
|
76
|
+
it { expect(subject.beginning_of_fortnight).to eq Date.parse('2014-01-01') }
|
77
|
+
it { expect(subject.end_of_fortnight).to eq Date.parse('2014-01-14') }
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'second fortnight of year' do
|
81
|
+
subject { Date.parse '2014-01-16' }
|
82
|
+
it { expect(subject.beginning_of_fortnight).to eq Date.parse('2014-01-15') }
|
83
|
+
it { expect(subject.end_of_fortnight).to eq Date.parse('2014-01-28') }
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'middle of year' do
|
87
|
+
subject { Date.parse '2014-06-13' }
|
88
|
+
it { expect(subject.beginning_of_fortnight).to eq Date.parse('2014-06-04') }
|
89
|
+
it { expect(subject.end_of_fortnight).to eq Date.parse('2014-06-17') }
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'last day of year' do
|
93
|
+
subject { Date.parse '2014-12-31' }
|
94
|
+
it { expect(subject.beginning_of_fortnight).to eq Date.parse('2014-12-31') }
|
95
|
+
it { expect(subject.end_of_fortnight).to eq Date.parse('2015-01-13') }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'calendar_month' do
|
100
|
+
|
101
|
+
subject { Date.parse '2014-01-01' }
|
102
|
+
|
103
|
+
context 'week begins Monday' do
|
104
|
+
it { expect(subject.beginning_of_calendar_month).to eq Date.parse('2013-12-30') }
|
105
|
+
it { expect(subject.end_of_calendar_month).to eq Date.parse('2014-02-02') }
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'week begins Sunday' do
|
109
|
+
it { expect(subject.beginning_of_calendar_month(:sunday)).to eq Date.parse('2013-12-29') }
|
110
|
+
it { expect(subject.end_of_calendar_month(:sunday)).to eq Date.parse('2014-02-01') }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -1,57 +1,57 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Time do
|
4
|
-
|
5
|
-
describe 'weekend' do
|
6
|
-
|
7
|
-
(0..6).each do |n|
|
8
|
-
context "Monday plus #{n} days" do
|
9
|
-
subject { Time.zone.parse('2014-01-06') + n.days }
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe 'fortnight' do
|
17
|
-
|
18
|
-
context 'first day of year' do
|
19
|
-
subject { Time.zone.parse '2014-01-01' }
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'second fortnight of year' do
|
25
|
-
subject { Time.zone.parse '2014-01-16' }
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'middle of year' do
|
31
|
-
subject { Time.zone.parse '2014-06-13' }
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
context 'last day of year' do
|
37
|
-
subject { Time.zone.parse '2014-12-31' }
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe 'calendar_month' do
|
44
|
-
|
45
|
-
subject { Time.zone.parse '2014-01-01' }
|
46
|
-
|
47
|
-
context 'week begins Monday' do
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'week begins Sunday' do
|
53
|
-
it { subject.beginning_of_calendar_month(:sunday).
|
54
|
-
it { subject.end_of_calendar_month(:sunday).
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Time do
|
4
|
+
|
5
|
+
describe 'weekend' do
|
6
|
+
|
7
|
+
(0..6).each do |n|
|
8
|
+
context "Monday plus #{n} days" do
|
9
|
+
subject { Time.zone.parse('2014-01-06') + n.days }
|
10
|
+
it { expect(subject.beginning_of_weekend).to eq Time.zone.parse('2014-01-11') }
|
11
|
+
it { expect(subject.end_of_weekend).to eq Time.zone.parse('2014-01-12').end_of_day }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'fortnight' do
|
17
|
+
|
18
|
+
context 'first day of year' do
|
19
|
+
subject { Time.zone.parse '2014-01-01' }
|
20
|
+
it { expect(subject.beginning_of_fortnight).to eq Time.zone.parse('2014-01-01') }
|
21
|
+
it { expect(subject.end_of_fortnight).to eq Time.zone.parse('2014-01-14').end_of_day }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'second fortnight of year' do
|
25
|
+
subject { Time.zone.parse '2014-01-16' }
|
26
|
+
it { expect(subject.beginning_of_fortnight).to eq Time.zone.parse('2014-01-15') }
|
27
|
+
it { expect(subject.end_of_fortnight).to eq Time.zone.parse('2014-01-28').end_of_day }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'middle of year' do
|
31
|
+
subject { Time.zone.parse '2014-06-13' }
|
32
|
+
it { expect(subject.beginning_of_fortnight).to eq Time.zone.parse('2014-06-04') }
|
33
|
+
it { expect(subject.end_of_fortnight).to eq Time.zone.parse('2014-06-17').end_of_day }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'last day of year' do
|
37
|
+
subject { Time.zone.parse '2014-12-31' }
|
38
|
+
it { expect(subject.beginning_of_fortnight).to eq Time.zone.parse('2014-12-31') }
|
39
|
+
it { expect(subject.end_of_fortnight).to eq Time.zone.parse('2015-01-13').end_of_day }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'calendar_month' do
|
44
|
+
|
45
|
+
subject { Time.zone.parse '2014-01-01' }
|
46
|
+
|
47
|
+
context 'week begins Monday' do
|
48
|
+
it { expect(subject.beginning_of_calendar_month).to eq Time.zone.parse('2013-12-30') }
|
49
|
+
it { expect(subject.end_of_calendar_month).to eq Time.zone.parse('2014-02-02').end_of_day }
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'week begins Sunday' do
|
53
|
+
it { expect(subject.beginning_of_calendar_month(:sunday)).to eq Time.zone.parse('2013-12-29') }
|
54
|
+
it { expect(subject.end_of_calendar_month(:sunday)).to eq Time.zone.parse('2014-02-01').end_of_day }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|