cure 0.1.1 → 0.4.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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +16 -3
  3. data/.tool-versions +1 -0
  4. data/Dockerfile +1 -1
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +25 -6
  7. data/README.md +59 -81
  8. data/docs/README.md +33 -0
  9. data/docs/about.md +219 -0
  10. data/docs/builder/add.md +52 -0
  11. data/docs/builder/black_white_list.md +83 -0
  12. data/docs/builder/copy.md +48 -0
  13. data/docs/builder/explode.md +70 -0
  14. data/docs/builder/main.md +43 -0
  15. data/docs/builder/remove.md +46 -0
  16. data/docs/examples/examples.md +164 -0
  17. data/docs/export/main.md +37 -0
  18. data/docs/extract/main.md +89 -0
  19. data/docs/metadata/main.md +29 -0
  20. data/docs/query/main.md +45 -0
  21. data/docs/sources/main.md +36 -0
  22. data/docs/transform/main.md +53 -0
  23. data/docs/validate/main.md +42 -0
  24. data/exe/cure +12 -37
  25. data/exe/cure.old +59 -0
  26. data/lib/cure/builder/base_builder.rb +151 -0
  27. data/lib/cure/builder/candidate.rb +56 -0
  28. data/lib/cure/cli/command.rb +105 -0
  29. data/lib/cure/cli/generate_command.rb +54 -0
  30. data/lib/cure/cli/new_command.rb +52 -0
  31. data/lib/cure/cli/run_command.rb +19 -0
  32. data/lib/cure/cli/templates/README.md.erb +1 -0
  33. data/lib/cure/cli/templates/gemfile.erb +5 -0
  34. data/lib/cure/cli/templates/gitignore.erb +181 -0
  35. data/lib/cure/cli/templates/new_template.rb.erb +31 -0
  36. data/lib/cure/cli/templates/tool-versions.erb +1 -0
  37. data/lib/cure/config.rb +151 -13
  38. data/lib/cure/coordinator.rb +108 -0
  39. data/lib/cure/database.rb +191 -0
  40. data/lib/cure/dsl/builder.rb +26 -0
  41. data/lib/cure/dsl/exporters.rb +45 -0
  42. data/lib/cure/dsl/extraction.rb +60 -0
  43. data/lib/cure/dsl/metadata.rb +33 -0
  44. data/lib/cure/dsl/queries.rb +36 -0
  45. data/lib/cure/dsl/source_files.rb +36 -0
  46. data/lib/cure/dsl/template.rb +131 -0
  47. data/lib/cure/dsl/transformations.rb +95 -0
  48. data/lib/cure/dsl/validator.rb +22 -0
  49. data/lib/cure/export/base_processor.rb +194 -0
  50. data/lib/cure/export/manager.rb +24 -0
  51. data/lib/cure/extract/base_processor.rb +47 -0
  52. data/lib/cure/extract/csv_lookup.rb +43 -0
  53. data/lib/cure/extract/extractor.rb +80 -0
  54. data/lib/cure/extract/filter.rb +118 -0
  55. data/lib/cure/extract/named_range.rb +94 -0
  56. data/lib/cure/extract/named_range_processor.rb +128 -0
  57. data/lib/cure/extract/variable.rb +25 -0
  58. data/lib/cure/extract/variable_processor.rb +57 -0
  59. data/lib/cure/generator/base_generator.rb +61 -0
  60. data/lib/cure/generator/case_generator.rb +32 -0
  61. data/lib/cure/generator/character_generator.rb +41 -0
  62. data/lib/cure/generator/erb_generator.rb +21 -0
  63. data/lib/cure/generator/eval_generator.rb +34 -0
  64. data/lib/cure/generator/faker_generator.rb +31 -0
  65. data/lib/cure/generator/guid_generator.rb +21 -0
  66. data/lib/cure/generator/hex_generator.rb +21 -0
  67. data/lib/cure/generator/imports.rb +16 -0
  68. data/lib/cure/generator/number_generator.rb +21 -0
  69. data/lib/cure/generator/placeholder_generator.rb +26 -0
  70. data/lib/cure/generator/proc_generator.rb +21 -0
  71. data/lib/cure/generator/redact_generator.rb +22 -0
  72. data/lib/cure/generator/static_generator.rb +21 -0
  73. data/lib/cure/generator/variable_generator.rb +26 -0
  74. data/lib/cure/helpers/file_helpers.rb +50 -0
  75. data/lib/cure/helpers/object_helpers.rb +17 -0
  76. data/lib/cure/helpers/perf_helpers.rb +30 -0
  77. data/lib/cure/helpers/string.rb +54 -0
  78. data/lib/cure/launcher.rb +125 -0
  79. data/lib/cure/log.rb +10 -3
  80. data/lib/cure/planner.rb +136 -0
  81. data/lib/cure/strategy/append_strategy.rb +28 -0
  82. data/lib/cure/strategy/base_strategy.rb +98 -0
  83. data/lib/cure/strategy/contain_strategy.rb +51 -0
  84. data/lib/cure/strategy/end_with_strategy.rb +52 -0
  85. data/lib/cure/strategy/full_strategy.rb +28 -0
  86. data/lib/cure/strategy/history/history_cache.rb +82 -0
  87. data/lib/cure/strategy/imports.rb +12 -0
  88. data/lib/cure/strategy/match_strategy.rb +48 -0
  89. data/lib/cure/strategy/prepend_strategy.rb +28 -0
  90. data/lib/cure/strategy/regex_strategy.rb +55 -0
  91. data/lib/cure/strategy/split_strategy.rb +58 -0
  92. data/lib/cure/strategy/start_with_strategy.rb +53 -0
  93. data/lib/cure/transformation/candidate.rb +47 -36
  94. data/lib/cure/transformation/transform.rb +29 -71
  95. data/lib/cure/validator/base_rule.rb +78 -0
  96. data/lib/cure/validator/candidate.rb +54 -0
  97. data/lib/cure/validator/manager.rb +21 -0
  98. data/lib/cure/validators.rb +71 -0
  99. data/lib/cure/version.rb +1 -1
  100. data/lib/cure.rb +19 -6
  101. data/templates/dsl_example.rb +48 -0
  102. data/templates/empty_template.rb +31 -0
  103. metadata +161 -23
  104. data/lib/cure/csv_helpers.rb +0 -6
  105. data/lib/cure/export/exporter.rb +0 -49
  106. data/lib/cure/file_helpers.rb +0 -38
  107. data/lib/cure/generator/base.rb +0 -148
  108. data/lib/cure/main.rb +0 -63
  109. data/lib/cure/object_helpers.rb +0 -27
  110. data/lib/cure/strategy/base.rb +0 -223
  111. data/templates/aws_cur_template.json +0 -143
  112. data/templates/example_template.json +0 -38
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class StartWithStrategy < BaseStrategy
8
+ # validates :match
9
+
10
+ # Additional details needed to make substitution.
11
+ # @return [StartWithStrategyParams]
12
+ attr_accessor :params
13
+
14
+ def initialize(options)
15
+ super(StartWithStrategyParams.new(options))
16
+ end
17
+
18
+ # gsub catchment group
19
+ # @param [String] source_value
20
+ def _retrieve_value(source_value)
21
+ @params.match || nil if source_value.start_with? @params.match
22
+ end
23
+
24
+ # @param [String] source_value
25
+ # @param [String] generated_value
26
+ # @return [String]
27
+ def _replace_value(source_value, generated_value)
28
+ return unless source_value.start_with? @params.match
29
+
30
+ return generated_value unless replace_partial_record
31
+
32
+ @params.match + generated_value
33
+ end
34
+
35
+ def _describe
36
+ "Start with replacement will look for '#{@params.match}'. " \
37
+ "It will do a #{replace_partial_record ? "partial" : "full"} replacement. " \
38
+ "[Note: If the value does not include '#{@params.match}', no substitution is made.]"
39
+ end
40
+ end
41
+
42
+ class StartWithStrategyParams < BaseStrategyParams
43
+ attr_reader :match
44
+
45
+ validates :match
46
+
47
+ def initialize(options=nil)
48
+ @match = options[:match]
49
+ super(options)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,86 +1,97 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cure/object_helpers"
4
- require "cure/strategy/base"
5
- require "cure/generator/base"
3
+ require "cure/helpers/object_helpers"
4
+ require "cure/strategy/imports"
5
+ require "cure/generator/imports"
6
+ require "cure/extract/extractor"
6
7
  require "cure/log"
7
8
 
8
9
  module Cure
9
10
  module Transformation
10
11
  # Per row, we will have a candidate for each transformation that needs to be made
11
12
  class Candidate
12
- include ObjectHelpers
13
+ include Helpers::ObjectHelpers
13
14
  include Log
14
15
 
16
+ # Named range that column exists in
17
+ # @return [String]
18
+ attr_reader :named_range
19
+
15
20
  # Lookup column name for CSV.
16
21
  # @return [String]
17
- attr_accessor :column
22
+ attr_reader :column
18
23
 
19
24
  # What sort of data needs to be generated.
20
25
  # @return [List<Translation>]
21
26
  attr_reader :translations
22
27
 
28
+ # @return [Translation]
23
29
  attr_reader :no_match_translation
24
30
 
25
- # @param [String] source_value
26
- # @return [String]
31
+ attr_reader :ignore_empty
32
+
33
+ def initialize(column, named_range: Cure::Extraction.default_named_range, options: {})
34
+ @column = column
35
+ @named_range = named_range
36
+ @ignore_empty = options.fetch(:ignore_empty, false)
37
+
38
+ @translations = []
39
+ @no_match_translation = nil
40
+ end
41
+
42
+ # @param [String, Nil] source_value
43
+ # @param [RowCtx] row_ctx
44
+ # @return [String,nil]
27
45
  # Transforms the existing value
28
- def perform(source_value)
29
- # log_debug("Performing substitution for [#{@column}] with [#{@translations.length}] translations")
46
+ def perform(source_value, row_ctx)
30
47
  value = source_value
31
48
 
32
49
  @translations.each do |translation|
33
- temp = translation.extract(value)
50
+ temp = translation.extract(value, row_ctx)
34
51
  value = temp if temp
35
52
  end
36
53
 
37
- if value == source_value
38
- log_debug("No translation made for #{value} [#{source_value}]")
39
- value = @no_match_translation&.extract(source_value)
40
- log_debug("Translated to #{value} from [#{source_value}]")
54
+ if value == source_value && @no_match_translation
55
+ log_trace("No translation made for #{value} [#{source_value}]")
56
+ value = @no_match_translation.extract(source_value, row_ctx)
57
+ log_trace("Translated to #{value} from [#{source_value}]")
41
58
  end
42
59
 
43
60
  value
44
61
  end
45
62
 
46
- def translations=(opts)
47
- @translations = opts.map { |o| Translation.new.from_hash(o) }
63
+ def with_translations(translations)
64
+ @translations = translations
65
+ self
48
66
  end
49
67
 
50
- def no_match_translation=(opts)
51
- @no_match_translation = Translation.new.from_hash(opts)
68
+ def with_no_match_translation(no_match_translation)
69
+ @no_match_translation = no_match_translation
70
+ self
52
71
  end
53
72
  end
54
73
 
55
74
  class Translation
56
- include ObjectHelpers
75
+ include Helpers::ObjectHelpers
57
76
 
58
77
  # What sort of replacement is done, full/random/lookup/partial.
59
- # @return [Strategy::Base]
78
+ # @return [Strategy::BaseStrategy]
60
79
  attr_reader :strategy
61
80
 
62
81
  # What sort of data needs to be generated.
63
- # @return [Generator::Base]
82
+ # @return [Generator::BaseGenerator]
64
83
  attr_reader :generator
65
84
 
66
- # @param [String] source_value
67
- # @return [String]
68
- def extract(source_value)
69
- @strategy.extract(source_value, @generator)
70
- end
71
-
72
- # @param [Hash] opts
73
- def strategy=(opts)
74
- clazz_name = "Cure::Strategy::#{opts["name"].to_s.capitalize}Strategy"
75
- @strategy = Kernel.const_get(clazz_name).new(opts["options"] || {})
85
+ def initialize(strategy, generator)
86
+ @strategy = strategy
87
+ @generator = generator
76
88
  end
77
89
 
78
- # @param [Hash] opts
79
- def generator=(opts)
80
- clazz_name = "Cure::Generator::#{opts["name"].to_s.capitalize}Generator"
81
- @generator = Kernel.const_get(clazz_name).new(opts["options"] || {})
90
+ # @param [String] source_value
91
+ # @return [String]
92
+ def extract(source_value, row_ctx)
93
+ @strategy.extract(source_value, row_ctx, @generator)
82
94
  end
83
95
  end
84
96
  end
85
97
  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,87 +23,40 @@ module Cure
18
23
  @candidates = candidates
19
24
  end
20
25
 
21
- # @param [String] csv_file_location
22
- # @return [TransformContext]
23
- def extract_from_file(csv_file_location)
24
- file_contents = read_file(csv_file_location)
25
- extract_from_contents(file_contents)
26
- end
27
-
28
- # @param [String] file_contents
29
- # @return [TransformContext]
30
- def extract_from_contents(file_contents)
31
- ctx = TransformContext.new
32
- parse_content(ctx, file_contents, header: :none) do |row|
33
- if ctx.row_count == 1
34
- ctx.extract_column_headers(row)
35
- next
36
- end
37
-
38
- row = transform(ctx.column_headers, row)
39
- ctx.add_transformed_row(row)
40
- end
26
+ # @param [Hash] row
27
+ # @return [Hash]
28
+ def transform(row)
29
+ original_row = row.dup
41
30
 
42
- ctx
43
- end
31
+ @candidates.each do |candidate|
32
+ column = candidate.column.to_sym
44
33
 
45
- private
34
+ next unless row.key?(column)
46
35
 
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?
36
+ existing_value = row[column]
37
+ next if existing_value.nil? && candidate.ignore_empty
56
38
 
57
- Rcsv.parse(file_contents, opts) do |row|
58
- ctx.row_count += 1
59
- yield row
39
+ new_value = candidate.perform(existing_value, RowCtx.new(row, original_row: original_row)) # transform value
40
+ row[column] = new_value
60
41
  end
61
- end
62
-
63
- # @param [Hash] column_headers
64
- # @param [Array] row
65
- # @return [Array]
66
- def transform(column_headers, row)
67
- @candidates.each do |candidate|
68
- column_idx = column_headers[candidate.column]
69
- next unless column_idx
70
-
71
- existing_value = row[column_idx]
72
- next unless existing_value
73
42
 
74
- new_value = candidate.perform(existing_value) # transform value
75
- row[column_idx] = new_value
76
- end
43
+ remove_system_columns(row)
44
+ end
77
45
 
46
+ def remove_system_columns(row)
47
+ row.delete(:_id)
78
48
  row
79
49
  end
80
50
  end
81
51
 
82
- class TransformContext
83
- include FileHelpers
84
-
85
- attr_accessor :row_count,
86
- :transformed_rows,
87
- :column_headers
88
-
89
- def initialize
90
- @row_count = 0
91
- @transformed_rows = []
92
- @column_headers = {}
93
- end
94
-
95
- # @param [Array<String>] row
96
- def extract_column_headers(row)
97
- row.each_with_index { |column, idx| @column_headers[column] = idx }
98
- end
52
+ # This class looks useless, but it isn't. It exists purely to give a hook to add
53
+ # more stuff to a strategy in the future without the method signature changing
54
+ class RowCtx
55
+ attr_accessor :row, :original_row
99
56
 
100
- def add_transformed_row(row)
101
- @transformed_rows << row
57
+ def initialize(row, original_row: nil)
58
+ @row = row
59
+ @original_row = original_row
102
60
  end
103
61
  end
104
62
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/log"
4
+ require "cure/config"
5
+ require "cure/database"
6
+ require "cure/helpers/file_helpers"
7
+ require "cure/extract/extractor"
8
+
9
+ require "rcsv"
10
+
11
+ module Cure
12
+ module Validator
13
+ class BaseRule
14
+
15
+ def initialize(named_range, column, options)
16
+ @named_range = named_range
17
+ @column = column
18
+ @options = options
19
+ end
20
+
21
+ def process(_value)
22
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
23
+ end
24
+
25
+ def to_s
26
+ "Base Rule"
27
+ end
28
+ end
29
+
30
+ class NotNullRule < BaseRule
31
+ def process(value)
32
+ !value.nil?
33
+ end
34
+
35
+ def to_s
36
+ "Not null"
37
+ end
38
+ end
39
+
40
+ class LengthRule < BaseRule
41
+ def process(value)
42
+ return true if value.nil?
43
+ return true unless value.respond_to? :size
44
+
45
+ length = value.size
46
+ length >= min && length <= max
47
+ end
48
+
49
+ def to_s
50
+ "Length [Min: #{min}, Max: #{max}]"
51
+ end
52
+
53
+ def min
54
+ @min || @options.fetch(:max, 0)
55
+ end
56
+
57
+ def max
58
+ @max || @options.fetch(:max, 99_999)
59
+ end
60
+ end
61
+
62
+ class CustomRule < BaseRule
63
+ def process(value)
64
+ return true if value.nil?
65
+
66
+ custom_proc.call(value)
67
+ end
68
+
69
+ def to_s
70
+ "Custom"
71
+ end
72
+
73
+ def custom_proc
74
+ @options.fetch(:proc, proc { |_x| false })
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/helpers/object_helpers"
4
+ require "cure/validator/base_rule"
5
+ require "cure/log"
6
+
7
+ module Cure
8
+ module Validator
9
+ class Candidate
10
+ include Helpers::ObjectHelpers
11
+ include Log
12
+
13
+ # Named range that column exists in
14
+ # @return [String]
15
+ attr_reader :named_range
16
+
17
+ # Lookup column name for CSV.
18
+ # @return [String]
19
+ attr_reader :column
20
+
21
+ # # What sort of data needs to be generated.
22
+ # # @return [Array<Cure::Validator::BaseRule>]
23
+ attr_reader :rules
24
+
25
+ DEFAULT_OPTIONS = {
26
+ fail_on_error: false
27
+ }.freeze
28
+
29
+ def initialize(column, named_range, options={})
30
+ @column = column
31
+ @named_range = named_range || "_default"
32
+ @options = DEFAULT_OPTIONS.merge(options)
33
+ @rules = []
34
+ end
35
+
36
+ def perform(value)
37
+ result = @rules.filter_map do |rule|
38
+ rule.process(value) ? nil : "#{rule} failed -> [#{@column}][#{value}]"
39
+ end
40
+
41
+ raise "Validation failed:\n#{result.join("\n")}" if @options[:fail_on_error] && !result.empty?
42
+
43
+ result
44
+ end
45
+
46
+ def with_rule(method_name, options={})
47
+ klass_name = "Cure::Validator::#{method_name.to_s.split("_").map(&:capitalize).join}Rule"
48
+ raise "#{method_name} is not valid" unless class_exists?(klass_name)
49
+
50
+ @rules << Kernel.const_get(klass_name).new(@named_range, @column, options)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cure
4
+ module Export
5
+ class Manager
6
+
7
+ # @param [Array<Cure::Validator::BaseRule>] candidates
8
+ attr_reader :validators
9
+
10
+ def initialize(named_range, validators)
11
+ @named_range = named_range
12
+ @validators = validators
13
+ end
14
+
15
+ # @param [Hash] row
16
+ def process_row(row)
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -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:}
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cure
4
- VERSION = "0.1.1"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/cure.rb CHANGED
@@ -1,26 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "logger"
3
4
  require "cure/log"
5
+ require "cure/launcher"
4
6
  require "cure/config"
5
7
  require "cure/version"
6
-
7
- require "cure/file_helpers"
8
+ require "cure/dsl/template"
9
+ require "cure/strategy/imports"
10
+ require "cure/generator/imports"
8
11
  require "cure/transformation/transform"
9
-
10
- require "cure/main"
11
-
12
- require "logger"
12
+ require "cure/helpers/file_helpers"
13
13
 
14
14
  module Cure
15
15
  class << self
16
16
  attr_writer :logger
17
17
 
18
+ attr_reader :config
19
+
18
20
  def logger
19
21
  @logger ||= Logger.new($stdout).tap do |log|
20
22
  log.progname = name
23
+ log.formatter = proc do |severity, _datetime, _progname, msg|
24
+ "[#{severity}] #{msg}\n"
25
+ end
21
26
  end
22
27
  end
23
28
 
29
+ def init(&block)
30
+ launcher = Cure::Launcher.new
31
+ launcher.with_config(&block)
32
+ end
24
33
 
34
+ def init_from_file(file_path)
35
+ launcher = Cure::Launcher.new
36
+ launcher.with_config_file(file_path)
37
+ end
25
38
  end
26
39
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ sources do
4
+ csv :pathname, Pathname.new("spec/cure/e2e/input/simple_names.csv"), ref_name: "names"
5
+ csv :pathname, Pathname.new("spec/cure/e2e/input/simple_ages.csv"), ref_name: "ages"
6
+ end
7
+
8
+ extract do
9
+ named_range name: "section_1", at: "B2:G6"
10
+ named_range name: "section_2", at: "B18:G20", headers: "B2:G2"
11
+
12
+ variable name: "new_field", location: "A16"
13
+ variable name: "new_field_2", location: "B16"
14
+ end
15
+
16
+ query do
17
+ with named_range: "section_1", query: <<-SQL
18
+ SELECT * FROM section_1
19
+ SQL
20
+
21
+ with named_range: "section_2", query: <<-SQL
22
+ SELECT * FROM section_2
23
+ SQL
24
+ end
25
+
26
+ build do
27
+ candidate column: "new_column", named_range: "section_1" do
28
+ add options: {}
29
+ end
30
+ end
31
+
32
+ transform do
33
+ candidate column: "new_column", named_range: "section_1" do
34
+ with_translation { replace("full").with("variable", name: "new_field") }
35
+ end
36
+
37
+ candidate column: "new_column", named_range: "section_2" do
38
+ with_translation { replace("full").with("variable", name: "new_field") }
39
+ end
40
+
41
+ placeholders({key: "value", key2: "value2"})
42
+ end
43
+
44
+ export do
45
+ terminal named_range: "section_1", title: "Exported", limit_rows: 5
46
+ csv named_range: "section_1", file: "/tmp/cure/section_1.csv"
47
+ csv named_range: "section_2", file: "/tmp/cure/section_2.csv"
48
+ end
@@ -0,0 +1,31 @@
1
+ metadata do
2
+ # ...
3
+ end
4
+
5
+ sources do
6
+ # ...
7
+ end
8
+
9
+ extract do
10
+ # ...
11
+ end
12
+
13
+ validate do
14
+ # ...
15
+ end
16
+
17
+ build do
18
+ # ...
19
+ end
20
+
21
+ query do
22
+ # ...
23
+ end
24
+
25
+ transform do
26
+ # ...
27
+ end
28
+
29
+ export do
30
+ # ...
31
+ end