timely 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ad5b5230c51dc3ab72192b82882b333fe9fc72b49fb2e8324881e7a6b7fd269
4
- data.tar.gz: 1de47a9da2ee6f3708c049f85fed2654e7ec4900935056f80dbe42db2842cf7b
3
+ metadata.gz: e311a6b7b3b8f1c2c118f67e3cddc6ef7592091514c64f99c7a8d1f46f617d7a
4
+ data.tar.gz: ae6d6fa3c929fe97a63ed3e907544e97cafb38d2dc768f95d5cea00057d07864
5
5
  SHA512:
6
- metadata.gz: 8d9bde900b4005fdcf26cc826e53858eb47067f6ccd6e01c633861efb305970d37ceddfd7bc1d70b2c68bae1a53abccc178ca1b95f20fc5ae5032cc8ef0e3e11
7
- data.tar.gz: 8d1145ecf55ee9deb075d459e9f2399ec28bf0da6519f60b47cf1fddd679312383c6df4d9e83d8f6222e2aa89c7791b25927efb1705260e880ad54682b4b8037
6
+ metadata.gz: 4f0f48ab52cb955cd0dcc13b89138cc72dc5b444f87589173d346595d822bb12c205a5c93a27c34e5a5ea765807d521931823bd331c4baefa30a48a34e516829
7
+ data.tar.gz: 7013bcafe2fbed12b92caf1fc9da3b07292050fd643cd05a975495674cf5fbd206c815a4d9e65dafbbc25d2af8fb0c646f40a4cf839e4e8a03c08b1b795ec5d6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ * [TT-6193] Date group scopes for more efficient searches/restrictions
6
+
3
7
  ## 0.4.2
4
8
 
5
9
  * [TT-5794] Fix belongs_to associations are not explicitly marked optional
@@ -7,6 +7,32 @@ module Timely
7
7
  validates_presence_of :start_date, :end_date
8
8
  validate :validate_date_range!
9
9
 
10
+ scope :covering_date, lambda { |date|
11
+ # Suitable for use with joins/merge!
12
+ where(arel_table[:start_date].lteq(date)).where(arel_table[:end_date].gteq(date))
13
+ }
14
+
15
+ scope :within_range, lambda { |date_range|
16
+ # IMPORTANT: Required for correctness in case of string param.
17
+ dates = Array(date_range)
18
+ scope = covering_date(dates.first)
19
+ if dates.first != dates.last
20
+ scope = scope.or(covering_date(dates.last))
21
+ end
22
+ scope
23
+ }
24
+
25
+ scope :for_any_weekdays, lambda { |weekdays_int|
26
+ weekdays_int = weekdays_int.to_i
27
+ where((arel_table[:weekdays_bit_array] & weekdays_int).not_eq(0))
28
+ .or(where(weekdays_bit_array: nil))
29
+ }
30
+
31
+ scope :applying_for_duration, lambda { |date_range|
32
+ weekdays_int = Timely::WeekDays.from_range(date_range).weekdays_int
33
+ within_range(date_range).for_any_weekdays(weekdays_int)
34
+ }
35
+
10
36
  def includes_date?(date)
11
37
  date >= start_date && date <= end_date && weekdays.applies_for_date?(date)
12
38
  end
@@ -1,3 +1,3 @@
1
1
  module Timely
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -2,6 +2,16 @@ module Timely
2
2
  class WeekDays
3
3
  WEEKDAY_KEYS = %i[sun mon tue wed thu fri sat]
4
4
 
5
+ def self.from_range(date_range)
6
+ dates = Array(date_range)
7
+ return ALL_WEEKDAYS if dates.count >= WEEKDAY_KEYS.count
8
+
9
+ new(dates.each_with_object({}) { |date, result|
10
+ # e.g. {3: true, 5: true}
11
+ result[date.to_date.wday] = true
12
+ })
13
+ end
14
+
5
15
  # Create a new Weekdays object
6
16
  # weekdays can be in three formats
7
17
  # integer representing binary string
@@ -1,5 +1,7 @@
1
1
  require "spec_helper"
2
- describe Timely::DateGroup do
2
+
3
+
4
+ RSpec.describe Timely::DateGroup do
3
5
  before do
4
6
  @date_group = Timely::DateGroup.new(
5
7
  :start_date => '2000-01-01', :end_date => '2000-01-03', :weekdays => %w(1 1 1 1 1 1 1)
@@ -24,3 +26,58 @@ describe Timely::DateGroup do
24
26
  expect(@date_group.applicable_for_duration?(Timely::DateRange.new('2012-01-01'.to_date, '2012-01-03'.to_date))).to be true
25
27
  end
26
28
  end
29
+
30
+
31
+ RSpec.describe 'Timely::DateGroup.for_any_weekdays' do
32
+ let(:date_range) { ('2019-10-17'.to_date)..('2019-10-18'.to_date) }
33
+ let(:weekdays_int) { Timely::WeekDays.from_range(date_range).weekdays_int }
34
+
35
+ let(:special_group) {
36
+ Timely::DateGroup.create(start_date: date_range.first, end_date: date_range.last).tap { |date_group|
37
+ date_group.update_column(:weekdays_bit_array, nil)
38
+ }.reload
39
+ }
40
+
41
+ let!(:date_groups) { [
42
+ Timely::DateGroup.create(start_date: date_range.first, end_date: date_range.last, weekdays: { thu: true }),
43
+ Timely::DateGroup.create(start_date: date_range.first, end_date: date_range.last, weekdays: { mon: true }),
44
+ special_group,
45
+ ] }
46
+
47
+ RSpec.shared_examples 'finds expected date groups' do
48
+ it 'finds expected date groups' do
49
+ includes_date_groups.each do |date_group|
50
+ expect(date_group.includes_date?(date_range.first)).to eq(true)
51
+ end
52
+ expected_groups.each do |date_group|
53
+ expect(scoped_result).to include(date_group)
54
+ end
55
+ absent_groups.each do |date_group|
56
+ expect(date_group.includes_date?(date_range.first)).to eq(false)
57
+ expect(scoped_result).not_to include(date_group)
58
+ end
59
+ end
60
+ end
61
+
62
+ context '#within_range' do
63
+ let(:scoped_result) { Timely::DateGroup.within_range(date_range).to_a }
64
+ let(:expected_groups) { [ date_groups[0], date_groups[1], date_groups[2] ] }
65
+ let(:absent_groups) { [ ] }
66
+ let(:includes_date_groups) { [] }
67
+ it_behaves_like 'finds expected date groups'
68
+ end
69
+
70
+ let(:includes_date_groups) { expected_groups }
71
+ let(:expected_groups) { [ date_groups[0], date_groups[2] ] }
72
+ let(:absent_groups) { [ date_groups[1] ] }
73
+
74
+ context '#for_any_weekdays' do
75
+ let(:scoped_result) { Timely::DateGroup.for_any_weekdays(weekdays_int).to_a }
76
+ it_behaves_like 'finds expected date groups'
77
+ end
78
+
79
+ context '#applying_for_duration' do
80
+ let(:scoped_result) { Timely::DateGroup.applying_for_duration(date_range).to_a }
81
+ it_behaves_like 'finds expected date groups'
82
+ end
83
+ end
@@ -1,4 +1,4 @@
1
1
  require 'simplecov-rcov'
2
2
  require 'coveralls'
3
3
  require 'coverage/kit'
4
- Coverage::Kit.setup(minimum_coverage: 68.3)
4
+ Coverage::Kit.setup(minimum_coverage: 69.15)
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Timely::WeekDays do
3
+ RSpec.describe Timely::WeekDays do
4
4
  before do
5
5
  @weekdays = Timely::WeekDays.new(:tue => true, :thu => true)
6
6
  end
@@ -49,3 +49,26 @@ describe Timely::WeekDays do
49
49
  expect(Timely::WeekDays.new(%w(1 1 1 1 1 0 1)).all_days?).to be false
50
50
  end
51
51
  end
52
+
53
+ RSpec.describe 'Timely::WeekDays.from_range' do
54
+ {
55
+ 'single date as string': { date_range: '2019-10-17', expected_weekdays: [ :thu ] },
56
+ 'single date as object': { date_range: '2019-10-17'.to_date, expected_weekdays: [ :thu ] },
57
+ 'range with strings': {
58
+ date_range: '2019-10-17'..'2019-10-18',
59
+ expected_weekdays: [ :thu, :fri ],
60
+ },
61
+ 'range with objects': {
62
+ date_range: ('2019-10-17'.to_date)..('2019-10-18'.to_date),
63
+ expected_weekdays: [ :thu, :fri ],
64
+ },
65
+ }.each do |type, data|
66
+ it "#{type} has correct weekdays and applies for dates" do
67
+ weekdays = Timely::WeekDays.from_range(data[:date_range])
68
+ expect(weekdays.weekdays).to eq(data[:expected_weekdays])
69
+ Array(data[:date_range]).each do |date|
70
+ expect(weekdays.applies_for_date?(date.to_date)).to eq(true)
71
+ end
72
+ end
73
+ end
74
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timely
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Noack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-01 00:00:00.000000000 Z
11
+ date: 2019-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler