differential 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/README.md +27 -1
- data/lib/differential/calculator/group.rb +9 -0
- data/lib/differential/calculator/item.rb +22 -0
- data/lib/differential/calculator/totals.rb +4 -2
- data/lib/differential/differential.rb +1 -0
- data/lib/differential/version.rb +1 -1
- data/spec/differential/calculator/group_spec.rb +11 -0
- data/spec/differential/calculator/item_spec.rb +143 -1
- data/spec/spec_helper.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa747f8e377b675d626c4c49cd31f84a73ca9bf8
|
4
|
+
data.tar.gz: 4c3af655ca69988cffa9928a3debb84eaeb8206b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6758f520698fa56574aa43b44e52a798db2c116200abea0ecbae1f14df36171d8f407e4755522ff70b95ac6328fc6117511a2efa11c8552bea0ed59e7d167eb9
|
7
|
+
data.tar.gz: b9e7a247c19f542fdc06783b324612d4a1d7ee6f7f8c43ece8f2925a175be1b13b0ac113cd852138f1d412eb621b0f2951a85685cfa1b2f353a9bc5e54e9b4f3
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -2,11 +2,9 @@ language: ruby
|
|
2
2
|
rvm:
|
3
3
|
- 2.3.1
|
4
4
|
- 2.3.7
|
5
|
+
- 2.3.8
|
6
|
+
- 2.6.0
|
5
7
|
cache: bundler
|
6
8
|
script:
|
7
9
|
- bundle exec rubocop
|
8
10
|
- bundle exec rspec
|
9
|
-
notifications:
|
10
|
-
hipchat:
|
11
|
-
rooms:
|
12
|
-
secure: OpIo19mre1zR5gJlr1T7BD/jVBYadikM49ueC4HWPt3Wln6LlNM3G1gcXVw4A5Ppd7p+6251aOhLHA44HdjXSo+VrhfgiFO9tfkyNuVIrLxeZr/eQwEnv1JJlPJdL/y2sGsBS5WRIgo+txIkLflQ0zoDpvnR6zkWRaRYZcRWo+X9Q890VHRR0emHURX5Kqsi5sJjHac69uIRbEAtlvdd1KnfNXF6+2udMnH6Kb4BxrSUp6voQ+VTyTGM4f2uMInxvjTVNzCCLgb4zBa5KwZNjjLRXWwIsWC0jVia0IRNskaeoFkFQxsVb33kq55t8XxR/ZuHUr5exFUazPnEc3ht9L/GOCYX4qFwbVPyxwyVZ64hHLx3E5g4ozlVCvBH3MDqkoasep7x+Ml8RuA6lSM2hIM88Eo5g98wpXW2WPiHUTxbtIc/2qKTmMKPZI+J23tuR7kza/5kGyPlqKA5OXr++0MFIUtFhWs1iSSQnq0Anssfxd1EhXPKqR/vqpQVgNSpv/cJOMQInPHSkvcq7kMRQWxka9uXHFT1+YH3kYCsAB30bdp8IPMNKQuemGhqS7GZXke9M32Yx9TKykGyAkzv6NGSc1pUAEViGHuydm6mTdvXYBfTQ3ZE6SIP+Rx5/WCyAyPerADPMI26enlFzzSPucdVU8wErceH1Uq7AleVNFw=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 1.0.6 (January 11, 2019)
|
2
|
+
|
3
|
+
- Added Data Peeking for groups and items (group#data_peek, item#data_peek methods).
|
4
|
+
- Changed precision of Totals a_sigma, b_sigma, and delta to be BigDecimal with precision of 6.
|
5
|
+
|
6
|
+
## 1.0.5 (January 11, 2019)
|
7
|
+
|
8
|
+
- Added lexicographic ID sorting (report#sorted_groups and group#sorted_items methods.)
|
9
|
+
|
1
10
|
## 1.0.4 (December 21, 2018)
|
2
11
|
|
3
12
|
- Adjusted reader so it stores multipart ID's properly in the ID's data field.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -184,7 +184,33 @@ reader_config = {
|
|
184
184
|
}
|
185
185
|
```
|
186
186
|
|
187
|
-
In this example we are showing that a unique identifier for an employee is not just the employee's ID, but also the companies ID. The above configuration would output a dataset that is grouped by transport type and direction (i.e. Outbound Train, Inbound Train, Outbound Car, etc...) and lists each unique employee per company in each group.
|
187
|
+
In this example we are showing that a unique identifier for an employee is not just the employee's ID, but also the companies ID. The above configuration would output a dataset that is grouped by transport type and direction (i.e. Outbound Train, Inbound Train, Outbound Car, etc...) and lists each unique employee per company in each group.
|
188
|
+
|
189
|
+
### Data Peeking
|
190
|
+
|
191
|
+
*Raw data* is defined as the initial dataset(s) passed into Differential#calculate. The consumer application defines this raw data and what Differential does is parses, interprets, and pivots it based on the configuration sent in. By the time Differential is complete you will end up with a completely different result set than initially passed in. This does not mean you cannot trace back the raw data.
|
192
|
+
|
193
|
+
You still have access to the raw data after the data has been consumed and calculated within a report. An example of accessing this on a specific item would be:
|
194
|
+
|
195
|
+
````
|
196
|
+
item.data_peek(:name)
|
197
|
+
````
|
198
|
+
|
199
|
+
In the above example, the item would the first record added (precedence to side A, then B) and execute the field on the record's data value. If the data value is a hash, it will send it through the brackets [] method, if the data value is an object, it will check to see if it responds to field and call it if it can.
|
200
|
+
|
201
|
+
If you want to only check one side, you can also specify the side:
|
202
|
+
|
203
|
+
````
|
204
|
+
item.data_peek(:name, ::Differential::Calculator::Side::A) # item.data_peek(:name, :a)
|
205
|
+
item.data_peek(:name, ::Differential::Calculator::Side::B) # item.data_peek(:name, :b)
|
206
|
+
````
|
207
|
+
|
208
|
+
Data peeking also works at the group level, where it will look at the first item added:
|
209
|
+
|
210
|
+
````
|
211
|
+
group.data_peek(:name)
|
212
|
+
````
|
213
|
+
|
188
214
|
|
189
215
|
## Contributing
|
190
216
|
|
@@ -45,8 +45,17 @@ module Differential
|
|
45
45
|
self
|
46
46
|
end
|
47
47
|
|
48
|
+
def data_peek(field, side = nil)
|
49
|
+
first_item&.data_peek(field, side)
|
50
|
+
end
|
51
|
+
|
48
52
|
private
|
49
53
|
|
54
|
+
def first_item
|
55
|
+
# first() will return an array: [key, value], but we just want the value.
|
56
|
+
@items_by_id.first&.last
|
57
|
+
end
|
58
|
+
|
50
59
|
def upsert_item(record, side)
|
51
60
|
item_id_key = record.id.value
|
52
61
|
item_id = record.id
|
@@ -40,8 +40,30 @@ module Differential
|
|
40
40
|
self
|
41
41
|
end
|
42
42
|
|
43
|
+
def data_peek(field, side = nil)
|
44
|
+
data_object = record_peek(side)&.data
|
45
|
+
|
46
|
+
return nil unless data_object
|
47
|
+
|
48
|
+
if data_object.respond_to?(field)
|
49
|
+
data_object.send(field)
|
50
|
+
elsif data_object.respond_to?(:[])
|
51
|
+
data_object[field]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
43
55
|
private
|
44
56
|
|
57
|
+
def record_peek(side)
|
58
|
+
if [nil, A].include?(side) && a_records.any?
|
59
|
+
a_records
|
60
|
+
elsif [nil, B].include?(side) && b_records.any?
|
61
|
+
b_records
|
62
|
+
else
|
63
|
+
[]
|
64
|
+
end.first
|
65
|
+
end
|
66
|
+
|
45
67
|
def account_for_record(record, side)
|
46
68
|
case side
|
47
69
|
when A
|
@@ -16,15 +16,17 @@ module Differential
|
|
16
16
|
class Totals
|
17
17
|
include ::Differential::Calculator::Side
|
18
18
|
|
19
|
+
DIGITS = 6
|
20
|
+
|
19
21
|
attr_reader :a_sigma,
|
20
22
|
:a_size,
|
21
23
|
:b_sigma,
|
22
24
|
:b_size
|
23
25
|
|
24
26
|
def initialize
|
25
|
-
@a_sigma = 0
|
27
|
+
@a_sigma = BigDecimal(0, DIGITS)
|
26
28
|
@a_size = 0
|
27
|
-
@b_sigma = 0
|
29
|
+
@b_sigma = BigDecimal(0, DIGITS)
|
28
30
|
@b_size = 0
|
29
31
|
end
|
30
32
|
|
data/lib/differential/version.rb
CHANGED
@@ -41,4 +41,15 @@ describe ::Differential::Calculator::Group do
|
|
41
41
|
|
42
42
|
expect(actual_ids).to eq(expected_ids)
|
43
43
|
end
|
44
|
+
|
45
|
+
it 'should peek at data based on first item it finds' do
|
46
|
+
record = ::Differential::Parser::Record.new(id: '1',
|
47
|
+
group_id: group_id,
|
48
|
+
value: 1,
|
49
|
+
data: { name: 'Millie' })
|
50
|
+
|
51
|
+
group.add(record, ::Differential::Calculator::Side::A)
|
52
|
+
|
53
|
+
expect(group.data_peek(:name)).to eq(record.data[:name])
|
54
|
+
end
|
44
55
|
end
|
@@ -10,11 +10,153 @@
|
|
10
10
|
require './spec/spec_helper'
|
11
11
|
|
12
12
|
describe ::Differential::Calculator::Item do
|
13
|
-
let(:id) { '
|
13
|
+
let(:id) { '1' }
|
14
14
|
|
15
15
|
let(:item) { ::Differential::Calculator::Item.new(id) }
|
16
16
|
|
17
17
|
it 'should initialize correctly' do
|
18
18
|
expect(item.id).to eq(id)
|
19
19
|
end
|
20
|
+
|
21
|
+
context 'data peeking' do
|
22
|
+
let(:matt_data_hash) { { name: 'matt' } }
|
23
|
+
|
24
|
+
let(:matt_data_object) { OpenStruct.new(matt_data_hash) }
|
25
|
+
|
26
|
+
let(:matt_record) do
|
27
|
+
::Differential::Parser::Record.new(
|
28
|
+
id: '1',
|
29
|
+
group_id: '1',
|
30
|
+
value: 1,
|
31
|
+
data: matt_data_hash
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:matt_record_with_data_object) do
|
36
|
+
::Differential::Parser::Record.new(
|
37
|
+
id: '1',
|
38
|
+
group_id: '1',
|
39
|
+
value: 1,
|
40
|
+
data: matt_data_object
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:nick_record) do
|
45
|
+
::Differential::Parser::Record.new(
|
46
|
+
id: '1',
|
47
|
+
group_id: '1',
|
48
|
+
value: 2,
|
49
|
+
data: { name: 'nick' }
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:sam_record) do
|
54
|
+
::Differential::Parser::Record.new(
|
55
|
+
id: '1',
|
56
|
+
group_id: '1',
|
57
|
+
value: 3,
|
58
|
+
data: { name: 'sam' }
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:katie_record) do
|
63
|
+
::Differential::Parser::Record.new(
|
64
|
+
id: '1',
|
65
|
+
group_id: '1',
|
66
|
+
value: 4,
|
67
|
+
data: { name: 'katie' }
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should work when data is an object' do
|
72
|
+
item.add(matt_record_with_data_object, ::Differential::Calculator::Side::A)
|
73
|
+
|
74
|
+
expect(item.data_peek(:name)).to eq(matt_data_object.name)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should work when data is a hash' do
|
78
|
+
item.add(matt_record, ::Differential::Calculator::Side::A)
|
79
|
+
|
80
|
+
expect(item.data_peek(:name)).to eq(matt_data_hash[:name])
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when side is nil' do
|
84
|
+
it 'should peek side A when both sides have records' do
|
85
|
+
item.add(matt_record, ::Differential::Calculator::Side::A)
|
86
|
+
item.add(nick_record, ::Differential::Calculator::Side::A)
|
87
|
+
item.add(sam_record, ::Differential::Calculator::Side::B)
|
88
|
+
item.add(katie_record, ::Differential::Calculator::Side::B)
|
89
|
+
|
90
|
+
expect(item.data_peek(:name)).to eq(matt_record.data[:name])
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should peek side A when only side A has records' do
|
94
|
+
item.add(matt_record, ::Differential::Calculator::Side::A)
|
95
|
+
item.add(nick_record, ::Differential::Calculator::Side::A)
|
96
|
+
|
97
|
+
expect(item.data_peek(:name)).to eq(matt_record.data[:name])
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should peek side B when only side B has records' do
|
101
|
+
item.add(sam_record, ::Differential::Calculator::Side::B)
|
102
|
+
item.add(katie_record, ::Differential::Calculator::Side::B)
|
103
|
+
|
104
|
+
expect(item.data_peek(:name)).to eq(sam_record.data[:name])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when side is A' do
|
109
|
+
let(:side) { ::Differential::Calculator::Side::A }
|
110
|
+
|
111
|
+
it 'should peek side A when both sides have records' do
|
112
|
+
item.add(matt_record, ::Differential::Calculator::Side::A)
|
113
|
+
item.add(nick_record, ::Differential::Calculator::Side::A)
|
114
|
+
item.add(sam_record, ::Differential::Calculator::Side::B)
|
115
|
+
item.add(katie_record, ::Differential::Calculator::Side::B)
|
116
|
+
|
117
|
+
expect(item.data_peek(:name, side)).to eq(matt_record.data[:name])
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should peek side A when only side A has records' do
|
121
|
+
item.add(matt_record, ::Differential::Calculator::Side::A)
|
122
|
+
item.add(nick_record, ::Differential::Calculator::Side::A)
|
123
|
+
|
124
|
+
expect(item.data_peek(:name, side)).to eq(matt_record.data[:name])
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should return nil when only side B has records' do
|
128
|
+
item.add(sam_record, ::Differential::Calculator::Side::B)
|
129
|
+
item.add(katie_record, ::Differential::Calculator::Side::B)
|
130
|
+
|
131
|
+
expect(item.data_peek(:name, side)).to eq(nil)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when side is B' do
|
136
|
+
let(:side) { ::Differential::Calculator::Side::B }
|
137
|
+
|
138
|
+
it 'should peek side B when both sides have records' do
|
139
|
+
item.add(matt_record, ::Differential::Calculator::Side::A)
|
140
|
+
item.add(nick_record, ::Differential::Calculator::Side::A)
|
141
|
+
item.add(sam_record, ::Differential::Calculator::Side::B)
|
142
|
+
item.add(katie_record, ::Differential::Calculator::Side::B)
|
143
|
+
|
144
|
+
expect(item.data_peek(:name, side)).to eq(sam_record.data[:name])
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should peek side B when only side B has records' do
|
148
|
+
item.add(sam_record, ::Differential::Calculator::Side::B)
|
149
|
+
item.add(katie_record, ::Differential::Calculator::Side::B)
|
150
|
+
|
151
|
+
expect(item.data_peek(:name, side)).to eq(sam_record.data[:name])
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should return nil when only side A has records' do
|
155
|
+
item.add(matt_record, ::Differential::Calculator::Side::A)
|
156
|
+
item.add(nick_record, ::Differential::Calculator::Side::A)
|
157
|
+
|
158
|
+
expect(item.data_peek(:name, side)).to eq(nil)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
20
162
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: differential
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: guard-rspec
|