realize 1.0.0.pre.alpha.1 → 1.0.0.pre.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +86 -2
- data/lib/realize.rb +2 -5
- data/lib/realize/collection/sort.rb +2 -2
- data/lib/realize/format/remove_whitespace.rb +0 -2
- data/lib/realize/pipeline.rb +3 -6
- data/lib/realize/value/blank.rb +0 -2
- data/lib/realize/value/null.rb +0 -2
- data/lib/realize/value/verbatim.rb +0 -5
- data/lib/realize/version.rb +1 -1
- data/realize.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 289c0fa13f4421249a59e82ce767881f04bd47bea5d0b3a4eb4db503b37add28
|
4
|
+
data.tar.gz: f8575e76151f98fc0e34d8fcf4c50231294ffad0f037eb6f276fd1393f8e6cd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf1f9808bdb3870860155d3eecf6187b4bb9a5b3b4ea755552a125e9a96fb34173d3174d2ba98c5da9aeef00dea520e3d2cf2b2f7821daa4b2d3c6558f8cec21
|
7
|
+
data.tar.gz: ec3bc0d03c004d8481b4d1d9b690076f9dd48988e9e957cd61c82aac40e77d60401666057dc9484b4ea8d6d116ed781305af49b0dcdf0d2bdfe77583393fc931
|
data/README.md
CHANGED
@@ -2,7 +2,11 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/realize.svg)](https://badge.fury.io/rb/realize) [![Build Status](https://travis-ci.org/bluemarblepayroll/realize.svg?branch=master)](https://travis-ci.org/bluemarblepayroll/realize) [![Maintainability](https://api.codeclimate.com/v1/badges/115f0c5a1d0a4cce7230/maintainability)](https://codeclimate.com/github/bluemarblepayroll/realize/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/115f0c5a1d0a4cce7230/test_coverage)](https://codeclimate.com/github/bluemarblepayroll/realize/test_coverage) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
4
4
|
|
5
|
-
|
5
|
+
This library provides a pluggable and configurable data transformation framework. The general use-case is:
|
6
|
+
|
7
|
+
> We need to be able to configure the data transformation pipeline, within an application, for a system-to-system integration.
|
8
|
+
|
9
|
+
It is currently used in production at Blue Marble to power the transformation pipeline within a larger ETL framework.
|
6
10
|
|
7
11
|
## Installation
|
8
12
|
|
@@ -20,7 +24,87 @@ bundle add realize
|
|
20
24
|
|
21
25
|
## Examples
|
22
26
|
|
23
|
-
|
27
|
+
### Basic Transformer Example
|
28
|
+
|
29
|
+
Here is a simple record we will use for data derivation and transformation:
|
30
|
+
|
31
|
+
````ruby
|
32
|
+
record = {
|
33
|
+
id: 1,
|
34
|
+
created_at: '2020-03-04T12:34:56Z',
|
35
|
+
first: 'Frank',
|
36
|
+
last: 'Rizzo'
|
37
|
+
}
|
38
|
+
````
|
39
|
+
|
40
|
+
Let's say we wanted to retrieve the created_at formatted as: 'MM/DD/YY', we could write:
|
41
|
+
|
42
|
+
````ruby
|
43
|
+
transformers = [
|
44
|
+
{
|
45
|
+
type: 'r/value/resolve',
|
46
|
+
key: :created_at
|
47
|
+
},
|
48
|
+
{
|
49
|
+
type: 'r/format/date',
|
50
|
+
output_format: '%D'
|
51
|
+
}
|
52
|
+
]
|
53
|
+
|
54
|
+
value = Realize.pipeline(transformers).transform(record) # 03/04/20
|
55
|
+
````
|
56
|
+
|
57
|
+
Notice how all built-in transformers are prefixed with 'r'. This should help isolate the built-in transformers from potential externally registered transformers.
|
58
|
+
|
59
|
+
### Transformer Gallery
|
60
|
+
|
61
|
+
Here is a list of each built-in transformer, their options, and what their function is:
|
62
|
+
|
63
|
+
#### Collection-oriented Transformers
|
64
|
+
|
65
|
+
* **r/collection/sort** [key, direction]: Takes an array (or coerces value to an array) and sort it either ascending or descending by some defined key's value.
|
66
|
+
|
67
|
+
#### Filtering Transformers
|
68
|
+
|
69
|
+
* **r/filter/by_key_record_value** [key, value]: Takes an array (or coerces value to an array) and selects only the records that match the key's value. In this case the value is derived off of the main record.
|
70
|
+
* **r/filter/by_key_value_presence** [key]: Takes an array (or coerces value to an array) and selects only the records where the key's value is present (not nil and not empty).
|
71
|
+
* **r/filter/by_key_record_value** [key, value]: Takes an array (or coerces value to an array) and selects only the records that match the key's value. In this case, the value is statically defined.
|
72
|
+
* **r/filter/inactive** [key, value]: Takes an array (or coerces value to an array) and selects only the records where the current time is between the start and end times as derived from the record. Note that *current time* can be passed in but defaults to current UTC time.
|
73
|
+
|
74
|
+
#### Format-oriented Transformers
|
75
|
+
|
76
|
+
* **r/format/date** [input_format, output_format]: Parses the incoming value into a Time object using the configured input_format and outputs it as formatted by the configured output_format.
|
77
|
+
* **r/format/remove_whitespace** []: Removes all whitespace from the incoming value.
|
78
|
+
* **r/format/string_replace** [original, replacement]: Replaces all occurrences of the configured original value with the replacement value.
|
79
|
+
|
80
|
+
#### Logical Transformers
|
81
|
+
|
82
|
+
* **r/logical/switch** [cases, default_transformers, key]: Provides a value-based logic branching. If a value matches a specific case, the specific cases transformers will be executed. If it does not match any case then the default_transformers will be executed.
|
83
|
+
|
84
|
+
#### Value-oriented Transformers
|
85
|
+
|
86
|
+
* **r/logical/blank** []: Always return a blank string.
|
87
|
+
* **r/logical/map** [values]: Do a lookup on the value using the `values` hash. If a value is found, then its corresponding value is returned. If it isn't then the input is returned.
|
88
|
+
* **r/logical/null** []: Always returns null.
|
89
|
+
* **r/logical/resolve** [key]: Dynamically resolves a value based on the record's key. It uses the [Objectable](https://github.com/bluemarblepayroll/objectable) library by default, which provides some goodies like dot-notation for nested objects and type-insensitivity (works for Ruby objects, hashes, structs, etc.)
|
90
|
+
* **r/logical/static** [value]: Always returns a hard-coded value.
|
91
|
+
* **r/logical/verbatim** []: Default transformer, simply echos back the input.
|
92
|
+
|
93
|
+
### Plugging in Transformers
|
94
|
+
|
95
|
+
Custom transformers can be externally created and registered as long as it complies with the general transformer interface:
|
96
|
+
|
97
|
+
* constructor accepts keyword arguments from which the configuration provides
|
98
|
+
* responds to a method called transform with the signature: transform(resolver, value, time, record)
|
99
|
+
|
100
|
+
After you have implemented the custom transformer, you can externally register is by:
|
101
|
+
|
102
|
+
````ruby
|
103
|
+
Realize::Transformers.register('some_custom_transformer', SomeCustomTransformer)
|
104
|
+
````
|
105
|
+
|
106
|
+
You should now be able to use the type: 'some_custom_transformer' within your transformation configuration.
|
107
|
+
|
24
108
|
|
25
109
|
## Contributing
|
26
110
|
|
data/lib/realize.rb
CHANGED
@@ -18,11 +18,8 @@ require_relative 'realize/pipeline'
|
|
18
18
|
# Top-level syntactic sugar.
|
19
19
|
module Realize
|
20
20
|
class << self
|
21
|
-
def pipeline(resolver: Objectable.resolver
|
22
|
-
Pipeline.new(
|
23
|
-
resolver: resolver,
|
24
|
-
transformers: transformers
|
25
|
-
)
|
21
|
+
def pipeline(transformers = [], resolver: Objectable.resolver)
|
22
|
+
Pipeline.new(transformers, resolver: resolver)
|
26
23
|
end
|
27
24
|
end
|
28
25
|
end
|
@@ -28,10 +28,10 @@ module Realize
|
|
28
28
|
freeze
|
29
29
|
end
|
30
30
|
|
31
|
-
def transform(
|
31
|
+
def transform(resolver, value, _time, _record)
|
32
32
|
records = array(value)
|
33
33
|
|
34
|
-
sorted = records.sort_by { |hsh| hsh
|
34
|
+
sorted = records.sort_by { |hsh| resolver.get(hsh, key) }
|
35
35
|
|
36
36
|
order == DESCENDING ? sorted.reverse : sorted
|
37
37
|
end
|
data/lib/realize/pipeline.rb
CHANGED
@@ -6,7 +6,7 @@ module Realize
|
|
6
6
|
class Pipeline
|
7
7
|
attr_reader :resolver, :transformers
|
8
8
|
|
9
|
-
def initialize(resolver: Objectable.resolver
|
9
|
+
def initialize(transformers = [], resolver: Objectable.resolver)
|
10
10
|
raise ArgumentError, 'resolver is required' unless resolver
|
11
11
|
|
12
12
|
@resolver = resolver
|
@@ -15,11 +15,8 @@ module Realize
|
|
15
15
|
freeze
|
16
16
|
end
|
17
17
|
|
18
|
-
def transform(record,
|
19
|
-
|
20
|
-
value = opts.fetch(:value, record)
|
21
|
-
|
22
|
-
transformers.inject(value) do |memo, transformer|
|
18
|
+
def transform(record, time = Time.now.utc)
|
19
|
+
transformers.inject(record) do |memo, transformer|
|
23
20
|
transformer.transform(resolver, memo, time, record)
|
24
21
|
end
|
25
22
|
end
|
data/lib/realize/value/blank.rb
CHANGED
data/lib/realize/value/null.rb
CHANGED
@@ -6,11 +6,6 @@ module Realize
|
|
6
6
|
class Verbatim
|
7
7
|
acts_as_hashable
|
8
8
|
|
9
|
-
# This is here to satisfy an underlying issue in acts_as_hashable.
|
10
|
-
# The #make calls in the factory and hashable module should be calling #new with no
|
11
|
-
# args if no keys are detected.
|
12
|
-
def initialize(_opts = {}); end
|
13
|
-
|
14
9
|
def transform(_resolver, value, _time, _record)
|
15
10
|
value
|
16
11
|
end
|
data/lib/realize/version.rb
CHANGED
data/realize.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
|
29
29
|
s.required_ruby_version = '>= 2.5'
|
30
30
|
|
31
|
-
s.add_dependency('acts_as_hashable', '
|
31
|
+
s.add_dependency('acts_as_hashable', '=1.2.0.pre.alpha')
|
32
32
|
s.add_dependency('objectable', '~>1')
|
33
33
|
|
34
34
|
s.add_development_dependency('guard-rspec', '~>4.7')
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: realize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.alpha.
|
4
|
+
version: 1.0.0.pre.alpha.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acts_as_hashable
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.2.0.pre.alpha
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.2.0.pre.alpha
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: objectable
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|