cure 0.1.1 → 0.1.2
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/.rubocop.yml +3 -0
- data/Gemfile.lock +1 -1
- data/README.md +16 -6
- data/exe/cure +7 -3
- data/lib/cure/config.rb +17 -3
- data/lib/cure/coordinator.rb +72 -0
- data/lib/cure/export/exporter.rb +32 -7
- data/lib/cure/extract/builder.rb +27 -0
- data/lib/cure/extract/csv_lookup.rb +32 -0
- data/lib/cure/extract/extractor.rb +123 -0
- data/lib/cure/generator/base_generator.rb +51 -0
- data/lib/cure/generator/case_generator.rb +25 -0
- data/lib/cure/generator/character_generator.rb +35 -0
- data/lib/cure/generator/faker_generator.rb +25 -0
- data/lib/cure/generator/guid_generator.rb +16 -0
- data/lib/cure/generator/hex_generator.rb +16 -0
- data/lib/cure/generator/imports.rb +12 -0
- data/lib/cure/generator/number_generator.rb +16 -0
- data/lib/cure/generator/placeholder_generator.rb +20 -0
- data/lib/cure/generator/redact_generator.rb +16 -0
- data/lib/cure/generator/variable_generator.rb +20 -0
- data/lib/cure/helpers/file_helpers.rb +40 -0
- data/lib/cure/helpers/object_helpers.rb +29 -0
- data/lib/cure/log.rb +3 -3
- data/lib/cure/main.rb +40 -31
- data/lib/cure/strategy/append_strategy.rb +24 -0
- data/lib/cure/strategy/base_strategy.rb +123 -0
- data/lib/cure/strategy/end_with_strategy.rb +46 -0
- data/lib/cure/strategy/full_strategy.rb +24 -0
- data/lib/cure/strategy/imports.rb +10 -0
- data/lib/cure/strategy/match_strategy.rb +43 -0
- data/lib/cure/strategy/regex_strategy.rb +49 -0
- data/lib/cure/strategy/split_strategy.rb +53 -0
- data/lib/cure/strategy/start_with_strategy.rb +47 -0
- data/lib/cure/template/dispatch.rb +30 -0
- data/lib/cure/template/extraction.rb +38 -0
- data/lib/cure/template/template.rb +28 -0
- data/lib/cure/template/transformations.rb +26 -0
- data/lib/cure/transformation/candidate.rb +23 -9
- data/lib/cure/transformation/transform.rb +33 -41
- data/lib/cure/validators.rb +71 -0
- data/lib/cure/version.rb +1 -1
- data/lib/cure.rb +9 -4
- data/templates/aws_cur_template.json +130 -128
- data/templates/example_template.json +46 -30
- metadata +36 -9
- data/lib/cure/csv_helpers.rb +0 -6
- data/lib/cure/file_helpers.rb +0 -38
- data/lib/cure/generator/base.rb +0 -148
- data/lib/cure/object_helpers.rb +0 -27
- data/lib/cure/strategy/base.rb +0 -223
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cure
|
4
|
+
# This name sucks, it is just an exporter
|
5
|
+
class Dispatch
|
6
|
+
|
7
|
+
# @param [Array<Hash>] named_ranges
|
8
|
+
attr_accessor :named_ranges
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@named_ranges = [default]
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [Array<String>] hash
|
15
|
+
# @return [Cure::Dispatch]
|
16
|
+
def self.from_hash(hash)
|
17
|
+
this = Cure::Dispatch.new
|
18
|
+
this.named_ranges = hash["sections"] if hash.key?("sections")
|
19
|
+
this
|
20
|
+
end
|
21
|
+
|
22
|
+
def default
|
23
|
+
{
|
24
|
+
"named_range" => "default",
|
25
|
+
"file_name" => "cure-export",
|
26
|
+
"type" => "csv"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cure
|
4
|
+
class Extraction
|
5
|
+
# @param [Array<Hash>] named_ranges
|
6
|
+
attr_accessor :named_ranges
|
7
|
+
|
8
|
+
# @param [Array<Hash>] named_ranges
|
9
|
+
attr_accessor :variables
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@named_ranges = [{
|
13
|
+
"name" => "default",
|
14
|
+
"section" => -1
|
15
|
+
}]
|
16
|
+
|
17
|
+
@variables = []
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [Hash] hash
|
21
|
+
# @return [Cure::Extraction]
|
22
|
+
def self.from_hash(hash)
|
23
|
+
this = Cure::Extraction.new
|
24
|
+
this.named_ranges.push(*hash["named_ranges"])
|
25
|
+
this.variables.push(*hash["variables"])
|
26
|
+
this
|
27
|
+
end
|
28
|
+
|
29
|
+
# We only need to get the named ranges where the candidates have specified
|
30
|
+
# interest in them.
|
31
|
+
#
|
32
|
+
# @param [Array] candidate_nrs
|
33
|
+
# @return [Array]
|
34
|
+
def required_named_ranges(candidate_nrs)
|
35
|
+
@named_ranges.select { |nr| candidate_nrs.include?(nr["name"]) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cure/template/transformations"
|
4
|
+
require "cure/template/extraction"
|
5
|
+
require "cure/template/dispatch"
|
6
|
+
|
7
|
+
module Cure
|
8
|
+
class Template
|
9
|
+
# @param [Cure::Transformations] transformations
|
10
|
+
attr_accessor :transformations
|
11
|
+
|
12
|
+
# @param [Cure::Extraction] extraction
|
13
|
+
attr_accessor :extraction
|
14
|
+
|
15
|
+
# @param [Cure::Dispatch] dispatch
|
16
|
+
attr_accessor :dispatch
|
17
|
+
|
18
|
+
# @param [Hash] hash
|
19
|
+
# @return [Cure::Template]
|
20
|
+
def self.from_hash(hash)
|
21
|
+
this = Cure::Template.new
|
22
|
+
this.transformations = Cure::Transformations.from_hash(hash.fetch("transformations", {}))
|
23
|
+
this.extraction = Cure::Extraction.from_hash(hash.fetch("extraction", {}))
|
24
|
+
this.dispatch = Cure::Dispatch.from_hash(hash.fetch("dispatch", {}))
|
25
|
+
this
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cure
|
4
|
+
class Transformations
|
5
|
+
# @param [Array<Transformation::Candidate>] candidates
|
6
|
+
attr_accessor :candidates
|
7
|
+
|
8
|
+
# @param [Array<Hash>] placeholders
|
9
|
+
# TODO: make class Placeholder
|
10
|
+
attr_accessor :placeholders
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@candidates = []
|
14
|
+
@placeholders = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [Hash] hash
|
18
|
+
# @return [Cure::Transformations]
|
19
|
+
def self.from_hash(hash)
|
20
|
+
this = Cure::Transformations.new
|
21
|
+
this.candidates = hash["candidates"].map { |c| Cure::Transformation::Candidate.new.from_json(c) }
|
22
|
+
this.placeholders = hash["placeholders"]
|
23
|
+
this
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,17 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "cure/object_helpers"
|
4
|
-
require "cure/strategy/
|
5
|
-
require "cure/generator/
|
3
|
+
require "cure/helpers/object_helpers"
|
4
|
+
require "cure/strategy/imports"
|
5
|
+
require "cure/generator/imports"
|
6
6
|
require "cure/log"
|
7
7
|
|
8
8
|
module Cure
|
9
9
|
module Transformation
|
10
10
|
# Per row, we will have a candidate for each transformation that needs to be made
|
11
11
|
class Candidate
|
12
|
-
include ObjectHelpers
|
12
|
+
include Helpers::ObjectHelpers
|
13
13
|
include Log
|
14
14
|
|
15
|
+
# Named range that column exists in
|
16
|
+
# @return [String]
|
17
|
+
attr_accessor :named_range
|
18
|
+
|
15
19
|
# Lookup column name for CSV.
|
16
20
|
# @return [String]
|
17
21
|
attr_accessor :column
|
@@ -20,8 +24,14 @@ module Cure
|
|
20
24
|
# @return [List<Translation>]
|
21
25
|
attr_reader :translations
|
22
26
|
|
27
|
+
# @return [Translation]
|
23
28
|
attr_reader :no_match_translation
|
24
29
|
|
30
|
+
def initialize
|
31
|
+
@translations = []
|
32
|
+
@named_range = "default"
|
33
|
+
end
|
34
|
+
|
25
35
|
# @param [String] source_value
|
26
36
|
# @return [String]
|
27
37
|
# Transforms the existing value
|
@@ -43,24 +53,26 @@ module Cure
|
|
43
53
|
value
|
44
54
|
end
|
45
55
|
|
56
|
+
# @param [Hash] opts
|
46
57
|
def translations=(opts)
|
47
58
|
@translations = opts.map { |o| Translation.new.from_hash(o) }
|
48
59
|
end
|
49
60
|
|
61
|
+
# @param [Hash] opts
|
50
62
|
def no_match_translation=(opts)
|
51
63
|
@no_match_translation = Translation.new.from_hash(opts)
|
52
64
|
end
|
53
65
|
end
|
54
66
|
|
55
67
|
class Translation
|
56
|
-
include ObjectHelpers
|
68
|
+
include Helpers::ObjectHelpers
|
57
69
|
|
58
70
|
# What sort of replacement is done, full/random/lookup/partial.
|
59
|
-
# @return [Strategy::
|
71
|
+
# @return [Strategy::BaseStrategy]
|
60
72
|
attr_reader :strategy
|
61
73
|
|
62
74
|
# What sort of data needs to be generated.
|
63
|
-
# @return [Generator::
|
75
|
+
# @return [Generator::BaseGenerator]
|
64
76
|
attr_reader :generator
|
65
77
|
|
66
78
|
# @param [String] source_value
|
@@ -72,7 +84,9 @@ module Cure
|
|
72
84
|
# @param [Hash] opts
|
73
85
|
def strategy=(opts)
|
74
86
|
clazz_name = "Cure::Strategy::#{opts["name"].to_s.capitalize}Strategy"
|
75
|
-
|
87
|
+
strategy = Kernel.const_get(clazz_name).new(opts["options"] || {})
|
88
|
+
|
89
|
+
@strategy = strategy
|
76
90
|
end
|
77
91
|
|
78
92
|
# @param [Hash] opts
|
@@ -80,7 +94,7 @@ module Cure
|
|
80
94
|
clazz_name = "Cure::Generator::#{opts["name"].to_s.capitalize}Generator"
|
81
95
|
@generator = Kernel.const_get(clazz_name).new(opts["options"] || {})
|
82
96
|
end
|
97
|
+
|
83
98
|
end
|
84
99
|
end
|
85
100
|
end
|
86
|
-
|
@@ -1,14 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "cure/log"
|
4
|
-
require "cure/file_helpers"
|
4
|
+
require "cure/helpers/file_helpers"
|
5
|
+
require "cure/config"
|
6
|
+
require "cure/extract/extractor"
|
7
|
+
|
5
8
|
require "rcsv"
|
6
9
|
|
7
10
|
module Cure
|
8
11
|
module Transformation
|
12
|
+
# Operational file for conducting transforms
|
9
13
|
class Transform
|
10
14
|
include Log
|
11
|
-
include FileHelpers
|
15
|
+
include Helpers::FileHelpers
|
16
|
+
include Configuration
|
12
17
|
|
13
18
|
# @return [Array<Candidate>]
|
14
19
|
attr_accessor :candidates
|
@@ -18,53 +23,34 @@ module Cure
|
|
18
23
|
@candidates = candidates
|
19
24
|
end
|
20
25
|
|
21
|
-
# @param [
|
22
|
-
# @return [
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
ctx.
|
35
|
-
|
26
|
+
# @param [ParsedCSV] parsed_content
|
27
|
+
# @return [Hash<String,TransformResult>] # make this transformation results?
|
28
|
+
def transform_content(parsed_content)
|
29
|
+
parsed_content.content.each_with_object({}) do |section, hash|
|
30
|
+
ctx = TransformResult.new
|
31
|
+
section["rows"].each do |row|
|
32
|
+
ctx.row_count += 1
|
33
|
+
|
34
|
+
if ctx.row_count == 1
|
35
|
+
ctx.extract_column_headers(row)
|
36
|
+
next
|
37
|
+
end
|
38
|
+
|
39
|
+
row = transform(section["name"], ctx.column_headers, row)
|
40
|
+
ctx.add_transformed_row(row)
|
36
41
|
end
|
37
42
|
|
38
|
-
|
39
|
-
ctx.add_transformed_row(row)
|
43
|
+
hash[section["name"]] = ctx
|
40
44
|
end
|
41
|
-
|
42
|
-
ctx
|
43
45
|
end
|
44
46
|
|
45
47
|
private
|
46
48
|
|
47
|
-
# @param [TransformContext] ctx
|
48
|
-
# @param [String] file_contents
|
49
|
-
# @param [Proc] _block
|
50
|
-
# @param [Hash] opts
|
51
|
-
# @yield [Array] row
|
52
|
-
# @yield [TransformContext] ctx
|
53
|
-
# @return [TransformContext]
|
54
|
-
def parse_content(ctx, file_contents, opts={}, &_block)
|
55
|
-
return nil unless block_given?
|
56
|
-
|
57
|
-
Rcsv.parse(file_contents, opts) do |row|
|
58
|
-
ctx.row_count += 1
|
59
|
-
yield row
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
49
|
# @param [Hash] column_headers
|
64
50
|
# @param [Array] row
|
65
51
|
# @return [Array]
|
66
|
-
def transform(column_headers, row)
|
67
|
-
|
52
|
+
def transform(named_range, column_headers, row)
|
53
|
+
candidates_for_named_range(named_range).each do |candidate|
|
68
54
|
column_idx = column_headers[candidate.column]
|
69
55
|
next unless column_idx
|
70
56
|
|
@@ -77,10 +63,16 @@ module Cure
|
|
77
63
|
|
78
64
|
row
|
79
65
|
end
|
66
|
+
|
67
|
+
# @param [String] named_range
|
68
|
+
# @return [Array<Cure::Transformation::Candidate>]
|
69
|
+
def candidates_for_named_range(named_range)
|
70
|
+
@candidates.select { |c| c.named_range == named_range }
|
71
|
+
end
|
80
72
|
end
|
81
73
|
|
82
|
-
class
|
83
|
-
include FileHelpers
|
74
|
+
class TransformResult
|
75
|
+
include Helpers::FileHelpers
|
84
76
|
|
85
77
|
attr_accessor :row_count,
|
86
78
|
:transformed_rows,
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cure
|
4
|
+
module Validators
|
5
|
+
# Should be an array, we can have multiple validators for the same obj
|
6
|
+
@validators = {}
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :validators
|
10
|
+
|
11
|
+
# @param [String] prop
|
12
|
+
# @param [Object] options
|
13
|
+
def register_validator(caller, prop, options)
|
14
|
+
@validators[caller] = [] unless @validators.has_key? caller
|
15
|
+
@validators[caller] << {prop: "@#{prop}".to_sym, options: options}
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [TrueClass, FalseClass]
|
19
|
+
def validate(zelf) # rubocop:disable Metrics/AbcSize
|
20
|
+
return true unless @validators.has_key? zelf.class
|
21
|
+
|
22
|
+
variables = instance_variables_hash(zelf)
|
23
|
+
@validators[zelf.class].all? do |k|
|
24
|
+
options = k[:options]
|
25
|
+
return true if options.empty? # No validator, no need to run.
|
26
|
+
|
27
|
+
validator_prop = options[:validator]
|
28
|
+
proc = case validator_prop
|
29
|
+
when Symbol
|
30
|
+
common_validators.fetch(validator_prop, proc { |_x| false })
|
31
|
+
when Proc
|
32
|
+
validator_prop
|
33
|
+
else
|
34
|
+
proc { |_x| false }
|
35
|
+
end
|
36
|
+
|
37
|
+
property = variables[k[:prop]]
|
38
|
+
proc.call(property)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [Object] zelf
|
43
|
+
# @return [Hash]
|
44
|
+
def instance_variables_hash(zelf)
|
45
|
+
zelf.instance_variables.each_with_object({}) do |attribute, hash|
|
46
|
+
hash[attribute] = zelf.instance_variable_get(attribute)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def common_validators
|
51
|
+
{
|
52
|
+
presence: proc { |current_val| !current_val.nil? }
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def validates(property, options={})
|
58
|
+
Validators.register_validator(self, property, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
module Helpers
|
62
|
+
def valid?(suppress_error: false)
|
63
|
+
status = Validators.validate(self)
|
64
|
+
return true if status
|
65
|
+
return false if suppress_error
|
66
|
+
|
67
|
+
raise "Object is invalid"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/cure/version.rb
CHANGED
data/lib/cure.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "cure/log"
|
4
|
+
require "cure/main"
|
4
5
|
require "cure/config"
|
5
6
|
require "cure/version"
|
7
|
+
require "cure/helpers/file_helpers"
|
6
8
|
|
7
|
-
require "cure/
|
9
|
+
require "cure/template/template"
|
8
10
|
require "cure/transformation/transform"
|
9
11
|
|
10
|
-
require "cure/main"
|
11
|
-
|
12
12
|
require "logger"
|
13
13
|
|
14
14
|
module Cure
|
@@ -21,6 +21,11 @@ module Cure
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
# @param [String] csv_file_location
|
25
|
+
# @param [Hash] template
|
26
|
+
# @return [File] output_file
|
27
|
+
def process(template, csv_file_location, output_dir)
|
28
|
+
# Main.init_from_hash(template, csv_file_location, output_dir)
|
29
|
+
end
|
25
30
|
end
|
26
31
|
end
|