periodic_records 0.2.1 → 0.3.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/.travis.yml +7 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile +5 -0
- data/README.md +64 -10
- data/lib/periodic_records/gapless.rb +76 -0
- data/lib/periodic_records/model.rb +1 -1
- data/lib/periodic_records/version.rb +1 -1
- data/lib/periodic_records.rb +1 -0
- data/periodic_records.gemspec +2 -2
- metadata +8 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ebc5b792de6c66cc8f858666775da5acbbbf67f2
|
|
4
|
+
data.tar.gz: 5f60cdab069337f62b3af5516035845f77aee527
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 94286105001f6fa005c6f40d162fb5d5d6058069eb1a65c9983d77ed307ad6246bf1c511e5dc7109508431c925cbd38b006776025ceae40928362b77295ce5a4
|
|
7
|
+
data.tar.gz: 9b8072aacca8ed7e270662715b23d5dbdd19d043232a79d52e30922aa4eae30d2d7ac260d7b885e43e1c350d07396a0e274dc58c584abdb183888de29828ef83
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.3.0] - 2018-01-16
|
|
7
|
+
|
|
8
|
+
- Support gapless records #2
|
|
9
|
+
|
|
6
10
|
## [0.2.1] - 2016-09-27
|
|
7
11
|
|
|
8
12
|
- Relax dependencies for Rails 5 compatibility
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -15,25 +15,25 @@ employment history.
|
|
|
15
15
|
|
|
16
16
|
Employees:
|
|
17
17
|
|
|
18
|
-
id | name
|
|
19
|
-
|
|
20
|
-
1 | John
|
|
18
|
+
| id | name |
|
|
19
|
+
|:---|:-----|
|
|
20
|
+
| 1 | John |
|
|
21
21
|
|
|
22
22
|
Employee assignments:
|
|
23
23
|
|
|
24
|
-
id | employee_id | start_at | end_at | job_title
|
|
25
|
-
|
|
26
|
-
1 | 1 | 2014-01-01 | 9999-01-01 | Developer
|
|
24
|
+
| id | employee_id | start_at | end_at | job_title |
|
|
25
|
+
|:---|:------------|:-----------|:-----------|:----------|
|
|
26
|
+
| 1 | 1 | 2014-01-01 | 9999-01-01 | Developer |
|
|
27
27
|
|
|
28
28
|
Now John is promoted to "Senior Developer" and you create a new employee
|
|
29
29
|
assignment record and this gem will take care of adjusting and splitting
|
|
30
30
|
overlapping records. In this case it will adjust the `end_at` field for the
|
|
31
31
|
previous assignment.
|
|
32
32
|
|
|
33
|
-
id | employee_id | start_at | end_at | job_title
|
|
34
|
-
|
|
35
|
-
1 | 1 | 2014-01-01 | 2018-05-04 | Developer
|
|
36
|
-
2 | 1 | 2018-05-05 | 9999-01-01 | Senior Developer
|
|
33
|
+
| id | employee_id | start_at | end_at | job_title |
|
|
34
|
+
|:---|:------------|:-----------|:-----------|:-----------------|
|
|
35
|
+
| 1 | 1 | 2014-01-01 | 2018-05-04 | Developer |
|
|
36
|
+
| 2 | 1 | 2018-05-05 | 9999-01-01 | Senior Developer |
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
## Installation
|
|
@@ -151,6 +151,60 @@ class AddEmployeeAssignmentsOverlappingDatesConstraint < ActiveRecord::Migration
|
|
|
151
151
|
end
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
+
## Gapless records
|
|
155
|
+
|
|
156
|
+
If you want to avoid gaps between records, you can include also `PeriodicRecords::Gapless`.
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
class EmployeeAssignment < ActiveRecord::Base
|
|
160
|
+
include PeriodicRecords::Model
|
|
161
|
+
include PeriodicRecords::Gapless
|
|
162
|
+
|
|
163
|
+
belongs_to :employee
|
|
164
|
+
|
|
165
|
+
def siblings
|
|
166
|
+
self.class.where(employee_id: employee_id).where.not(id: id)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Example:
|
|
172
|
+
|
|
173
|
+
| id | employee_id | start_at | end_at | job_title |
|
|
174
|
+
|:---|:------------|:-----------|:-----------|:-----------------|
|
|
175
|
+
| 1 | 1 | 0001-01-01 | 2018-01-15 | Junior Developer |
|
|
176
|
+
| 2 | 1 | 2018-01-16 | 2018-02-15 | Developer |
|
|
177
|
+
| 3 | 1 | 2018-02-16 | 9999-01-01 | Senior Developer |
|
|
178
|
+
|
|
179
|
+
If you update #2 from `2018-01-16 - 2018-02-15` to `2018-01-20 - 2018-02-10`, it
|
|
180
|
+
will also adjust end at for #1 and start at for #3 to avoid gaps between records.
|
|
181
|
+
|
|
182
|
+
After (with `Gapless`):
|
|
183
|
+
|
|
184
|
+
| id | employee_id | start_at | end_at | job_title |
|
|
185
|
+
|:---|:------------|:-----------|:-----------|:-----------------|
|
|
186
|
+
| 1 | 1 | 0001-01-01 | 2018-01-19 | Junior Developer |
|
|
187
|
+
| 2 | 1 | 2018-01-20 | 2018-02-10 | Developer |
|
|
188
|
+
| 3 | 1 | 2018-02-11 | 9999-01-01 | Senior Developer |
|
|
189
|
+
|
|
190
|
+
After (without `Gapless`):
|
|
191
|
+
|
|
192
|
+
| id | employee_id | start_at | end_at | job_title |
|
|
193
|
+
|:---|:------------|:-----------|:-----------|:-----------------|
|
|
194
|
+
| 1 | 1 | 0001-01-01 | 2018-01-15 | Junior Developer |
|
|
195
|
+
| 2 | 1 | 2018-01-20 | 2018-02-10 | Developer |
|
|
196
|
+
| 3 | 1 | 2018-02-16 | 9999-01-01 | Senior Developer |
|
|
197
|
+
|
|
198
|
+
If you delete #2 then it will adjust end at for #1.
|
|
199
|
+
|
|
200
|
+
You will not be able to delete entry that is at the beginning (#1) or at the end (#3).
|
|
201
|
+
|
|
202
|
+
You will not be able to adjust start at for the beginning entry (#1).
|
|
203
|
+
|
|
204
|
+
You will not be able to adjust end at for the ending entry (#3).
|
|
205
|
+
|
|
206
|
+
For more examples see [gapless_spec.rb](spec/periodic_records/gapless_spec.rb]).
|
|
207
|
+
|
|
154
208
|
## Development
|
|
155
209
|
|
|
156
210
|
After checking out the repo, run `bin/setup` to install dependencies.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module PeriodicRecords
|
|
2
|
+
module Gapless
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
validate :validate_gapless_start_at, if: :gapless?
|
|
7
|
+
validate :validate_gapless_end_at, if: :gapless?
|
|
8
|
+
after_save :adjust_gaps, if: :gapless?
|
|
9
|
+
before_destroy :before_gapless_destroy, if: :gapless?
|
|
10
|
+
after_destroy :after_gapless_destroy, if: :gapless?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def gapless?
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def validate_gapless_start_at
|
|
20
|
+
if start_at_changed? && start_at_was == self.class::MIN
|
|
21
|
+
errors.add :start_at, :invalid
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def validate_gapless_end_at
|
|
26
|
+
if end_at_changed? && end_at_was == self.class::MAX
|
|
27
|
+
errors.add :end_at, :invalid
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def adjust_gaps
|
|
32
|
+
adjust_previous_gap
|
|
33
|
+
adjust_next_gap
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def adjust_previous_gap
|
|
37
|
+
if saved_change_to_start_at? && start_at && start_at_before_last_save && start_at > start_at_before_last_save
|
|
38
|
+
previous_record = siblings.where(end_at: start_at_before_last_save - 1.day).first
|
|
39
|
+
if previous_record
|
|
40
|
+
previous_record.end_at = start_at - 1.day
|
|
41
|
+
previous_record.save(validate: false)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def adjust_next_gap
|
|
47
|
+
if saved_change_to_end_at? && end_at && end_at_before_last_save && end_at_before_last_save > end_at
|
|
48
|
+
next_record = siblings.where(start_at: end_at_before_last_save + 1.day).first
|
|
49
|
+
if next_record
|
|
50
|
+
next_record.start_at = end_at + 1.day
|
|
51
|
+
next_record.save(validate: false)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def before_gapless_destroy
|
|
57
|
+
if start_at == self.class::MIN
|
|
58
|
+
errors.add :start_at, :invalid
|
|
59
|
+
end
|
|
60
|
+
if end_at == self.class::MAX
|
|
61
|
+
errors.add :end_at, :invalid
|
|
62
|
+
end
|
|
63
|
+
unless errors.empty?
|
|
64
|
+
throw :abort
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def after_gapless_destroy
|
|
69
|
+
previous_record = siblings.where(end_at: start_at - 1.day).first
|
|
70
|
+
if previous_record
|
|
71
|
+
previous_record.end_at = end_at
|
|
72
|
+
previous_record.save(validate: false)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/periodic_records.rb
CHANGED
data/periodic_records.gemspec
CHANGED
|
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
20
20
|
spec.require_paths = ["lib"]
|
|
21
21
|
|
|
22
|
-
spec.add_runtime_dependency "activerecord", ">=
|
|
23
|
-
spec.add_runtime_dependency "activesupport", ">=
|
|
22
|
+
spec.add_runtime_dependency "activerecord", ">= 5.1"
|
|
23
|
+
spec.add_runtime_dependency "activesupport", ">= 5.1"
|
|
24
24
|
|
|
25
25
|
spec.add_development_dependency "bundler", "~> 1.9"
|
|
26
26
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: periodic_records
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Edgars Beigarts
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: exe
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2018-01-16 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activerecord
|
|
@@ -17,28 +17,28 @@ dependencies:
|
|
|
17
17
|
requirements:
|
|
18
18
|
- - ">="
|
|
19
19
|
- !ruby/object:Gem::Version
|
|
20
|
-
version: '
|
|
20
|
+
version: '5.1'
|
|
21
21
|
type: :runtime
|
|
22
22
|
prerelease: false
|
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
|
24
24
|
requirements:
|
|
25
25
|
- - ">="
|
|
26
26
|
- !ruby/object:Gem::Version
|
|
27
|
-
version: '
|
|
27
|
+
version: '5.1'
|
|
28
28
|
- !ruby/object:Gem::Dependency
|
|
29
29
|
name: activesupport
|
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
|
31
31
|
requirements:
|
|
32
32
|
- - ">="
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: '
|
|
34
|
+
version: '5.1'
|
|
35
35
|
type: :runtime
|
|
36
36
|
prerelease: false
|
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
|
38
38
|
requirements:
|
|
39
39
|
- - ">="
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: '
|
|
41
|
+
version: '5.1'
|
|
42
42
|
- !ruby/object:Gem::Dependency
|
|
43
43
|
name: bundler
|
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -115,6 +115,7 @@ files:
|
|
|
115
115
|
- bin/setup
|
|
116
116
|
- lib/periodic_records.rb
|
|
117
117
|
- lib/periodic_records/associations.rb
|
|
118
|
+
- lib/periodic_records/gapless.rb
|
|
118
119
|
- lib/periodic_records/model.rb
|
|
119
120
|
- lib/periodic_records/version.rb
|
|
120
121
|
- periodic_records.gemspec
|
|
@@ -138,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
138
139
|
version: '0'
|
|
139
140
|
requirements: []
|
|
140
141
|
rubyforge_project:
|
|
141
|
-
rubygems_version: 2.
|
|
142
|
+
rubygems_version: 2.6.10
|
|
142
143
|
signing_key:
|
|
143
144
|
specification_version: 4
|
|
144
145
|
summary: Support functions for ActiveRecord models with periodic entries
|