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,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/log"
4
+ require "cure/config"
5
+ require "cure/helpers/string"
6
+
7
+ require "artii"
8
+
9
+ module Cure
10
+ class Planner
11
+ include Configuration
12
+ include Log
13
+
14
+ def process
15
+ print_starter
16
+ print_extract_plan
17
+ print_build_plan
18
+ print_transformations_plan
19
+ print_ender
20
+ end
21
+
22
+ def print_starter # rubocop:disable Metrics/AbcSize
23
+ a = Artii::Base.new({font: "isometric1"})
24
+ puts a.asciify("C u r e")
25
+ puts "\nIf you require assistance, please read:"
26
+ puts "https://github.com/williamthom-as/cure/tree/main/docs\n"
27
+ puts ""
28
+ log_info "_______________________________________________"
29
+ print_spacer
30
+ log_info "Cure Execution Plan".bold.underline
31
+ log_info ""
32
+ log_info "Source file location: #{config.source_files.map(&:description).join(",")}"
33
+ log_info "Template file descriptor below"
34
+
35
+ print_spacer
36
+ end
37
+
38
+ def print_ender
39
+ log_info "_______________________________________________"
40
+ print_spacer
41
+ end
42
+
43
+ def print_extract_plan # rubocop:disable Metrics/AbcSize
44
+ print_title "Extract"
45
+ named_ranges = config.template.extraction.named_ranges
46
+ variables = config.template.extraction.variables
47
+
48
+ if named_ranges.empty?
49
+ print_empty(named_ranges, "If you wanted to add a named range, please read docs/extraction.md")
50
+ else
51
+ log_info("[#{named_ranges.length}] named ranges specified")
52
+ named_ranges.each do |nr|
53
+ log_info "-- #{nr.name} will extract values from #{nr.section}"
54
+ end
55
+ end
56
+
57
+ print_spacer
58
+
59
+ if variables.empty?
60
+ print_empty("variables")
61
+ else
62
+ log_info("[#{variables.length}] variables specified")
63
+ variables.each do |v|
64
+ log_info "-- #{v.name} will extract from #{v.location}"
65
+ end
66
+ end
67
+
68
+ print_spacer
69
+ end
70
+
71
+ def print_build_plan
72
+ print_title "Build"
73
+ candidates = config.template.builder.candidates
74
+
75
+ if candidates.empty?
76
+ print_empty("Build")
77
+ else
78
+ candidates.each do |c|
79
+ log_info "-- #{c.column || "Multiple columns>"} from #{c.named_range} will be changed with #{c.action}"
80
+ end
81
+ end
82
+
83
+ print_spacer
84
+ end
85
+
86
+ def print_transformations_plan # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity
87
+ print_title "Transforms"
88
+ candidates = config.template.transformations.candidates
89
+ placeholders = config.template.transformations.placeholders
90
+
91
+ if candidates.empty?
92
+ print_empty("Transforms")
93
+ else
94
+ candidates.each do |c|
95
+ log_info "-- #{c.column} from #{c.named_range} will be changed with #{c.translations.size} translation"
96
+ c.translations.each do |tr|
97
+ log_info "\t\t> #{"Replacement".bold} [#{tr.strategy.class}]: #{tr.strategy.describe}"
98
+ log_info "\t\t> #{"Generator".bold} [#{tr.generator.class}]: #{tr.generator.describe}"
99
+ end
100
+ end
101
+ end
102
+
103
+ print_spacer
104
+
105
+ if placeholders.nil? || placeholders.empty?
106
+ print_empty("Placeholders")
107
+ else
108
+ log_info "-- Variables"
109
+ placeholders.each do |k, v|
110
+ log_info "\t\t> #{k} => #{v}"
111
+ end
112
+ end
113
+
114
+ print_spacer
115
+ end
116
+
117
+ private
118
+
119
+ # @param [String] title
120
+ def print_title(title)
121
+ log_info title.bold.underline
122
+ print_spacer
123
+ end
124
+
125
+ # @param [String] descriptor
126
+ # @param [String,nil] remedy
127
+ def print_empty(descriptor, remedy=nil)
128
+ log_info "No #{descriptor} specified.".italic
129
+ log_info "[Remedy: #{remedy}]" unless remedy.nil?
130
+ end
131
+
132
+ def print_spacer
133
+ log_info ""
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class AppendStrategy < BaseStrategy
8
+ private
9
+
10
+ # @param [String] source_value
11
+ # @return [String]
12
+ def _retrieve_value(source_value)
13
+ source_value
14
+ end
15
+
16
+ # @param [String] source_value
17
+ # @param [String] generated_value
18
+ # @return [String]
19
+ def _replace_value(source_value, generated_value)
20
+ source_value + generated_value
21
+ end
22
+
23
+ def _describe
24
+ "Append generated value to the end of source value"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+ require "cure/validators"
5
+ require "cure/strategy/history/history_cache"
6
+
7
+ module Cure
8
+ module Strategy
9
+ class BaseStrategy
10
+ include History
11
+
12
+ # Additional details needed to make substitution.
13
+ # @return [BaseStrategyParams]
14
+ attr_accessor :params
15
+
16
+ def initialize(params)
17
+ # Is there a better way to do this? If its a base, we take a {}, if super
18
+ # defines it, we just use that instance.
19
+ @params = params.is_a?(Hash) ? BaseStrategyParams.new(params) : params
20
+ end
21
+
22
+ # @param [String] source_value
23
+ # @param [Transformation::RowCtx,nil] row_ctx
24
+ # @param [Generator::BaseGenerator] generator
25
+ # @return [String]
26
+ #
27
+ # This will retrieve the (partial) value, then generate a new replacement.
28
+ def extract(source_value, row_ctx, generator)
29
+ extracted_value = _retrieve_value(source_value)
30
+ existing = retrieve_history(extracted_value)
31
+
32
+ return _replace_value(source_value, existing) if existing && !@params.force_replace
33
+
34
+ generated_value = generator.generate(source_value, row_ctx)&.to_s
35
+ value = _replace_value(source_value, generated_value)
36
+
37
+ store_history(extracted_value, generated_value)
38
+
39
+ value
40
+ end
41
+
42
+ def describe
43
+ _describe
44
+ end
45
+
46
+ private
47
+
48
+ def replace_partial_record
49
+ replace_partial = @params.replace_partial
50
+ return replace_partial || false unless replace_partial.instance_of?(String)
51
+
52
+ (replace_partial || "true").to_s == "true"
53
+ end
54
+
55
+ def value?(value)
56
+ !value.nil? && value != ""
57
+ end
58
+
59
+ # @param [String] _source_value
60
+ def _retrieve_value(_source_value)
61
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
62
+ end
63
+
64
+ # @param [String] _source_value
65
+ # @param [String] _generated_value
66
+ # @return [String]
67
+ def _replace_value(_source_value, _generated_value)
68
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
69
+ end
70
+
71
+ def _describe
72
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
73
+ end
74
+ end
75
+
76
+ class BaseStrategyParams
77
+ include Validators::Helpers
78
+ extend Validators
79
+
80
+ # Additional details needed to make substitution.
81
+ # @return [Hash]
82
+ attr_accessor :options
83
+ attr_accessor :replace_partial, :force_replace
84
+
85
+ def initialize(options={})
86
+ @replace_partial = options[:replace_partial] || false
87
+ @force_replace = options[:force_replace] || false
88
+ @options = options
89
+
90
+ validate_params
91
+ end
92
+
93
+ def validate_params
94
+ valid?
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class ContainStrategy < BaseStrategy
8
+ # Additional details needed to make substitution.
9
+ # @return [ContainStrategyParams]
10
+ attr_accessor :params
11
+
12
+ def initialize(options)
13
+ super(ContainStrategyParams.new(options))
14
+ end
15
+
16
+ # @param [String] source_value
17
+ def _retrieve_value(source_value)
18
+ return unless source_value.include?(@params.match)
19
+
20
+ @params.match
21
+ end
22
+
23
+ # @param [String] source_value
24
+ # @param [String] generated_value
25
+ # @return [String]
26
+ def _replace_value(source_value, generated_value)
27
+ return unless source_value.include?(@params.match)
28
+
29
+ source_value.gsub(@params.match, generated_value)
30
+ end
31
+
32
+ def _describe
33
+ "Replacing matched value on '#{@params.match}') " \
34
+ "[Note: If the value does not include '#{@params.match}', no substitution is made.]"
35
+ end
36
+ end
37
+
38
+ class ContainStrategyParams < BaseStrategyParams
39
+ attr_reader :match
40
+
41
+ validates :match, validator: :presence
42
+
43
+ def initialize(options=nil)
44
+ @match = options[:match]
45
+ # valid?
46
+
47
+ super(options)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class EndWithStrategy < BaseStrategy
8
+ # Additional details needed to make substitution.
9
+ # @return [EndWithStrategyParams]
10
+ attr_accessor :params
11
+
12
+ def initialize(options)
13
+ super(EndWithStrategyParams.new(options))
14
+ end
15
+
16
+ # gsub catchment group
17
+ # @param [String] source_value
18
+ def _retrieve_value(source_value)
19
+ @params.match || nil if source_value.end_with? @params.match
20
+ end
21
+
22
+ # @param [String] source_value
23
+ # @param [String] generated_value
24
+ # @return [String]
25
+ def _replace_value(source_value, generated_value)
26
+ return unless source_value.end_with? @params.match
27
+
28
+ return generated_value unless replace_partial_record
29
+
30
+ generated_value + @params.match
31
+ # generated_value + source_value.reverse.chomp(@options["match"].reverse).reverse
32
+ end
33
+
34
+ def _describe
35
+ "End with replacement will look for '#{@params.match}'. " \
36
+ "It will do a #{replace_partial_record ? "partial" : "full"} replacement. " \
37
+ "[Note: If the value does not include '#{@params.match}', no substitution is made.]"
38
+ end
39
+ end
40
+
41
+ class EndWithStrategyParams < BaseStrategyParams
42
+ attr_reader :match
43
+
44
+ validates :match
45
+
46
+ def initialize(options=nil)
47
+ @match = options[:match]
48
+ super(options)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class FullStrategy < BaseStrategy
8
+ private
9
+
10
+ # @param [String] source_value
11
+ # @return [String]
12
+ def _retrieve_value(source_value)
13
+ source_value
14
+ end
15
+
16
+ # @param [String] _source_value
17
+ # @param [String] generated_value
18
+ # @return [String]
19
+ def _replace_value(_source_value, generated_value)
20
+ generated_value
21
+ end
22
+
23
+ def _describe
24
+ "Full replacement of source value with generated value."
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/database"
4
+
5
+ # Singleton Strategy for storing data across all processes
6
+
7
+ module Cure
8
+ module History
9
+
10
+ # @return [HistoryCache]
11
+ def history
12
+ HistoryCache.instance
13
+ end
14
+
15
+ # @return [String]
16
+ def retrieve_history(source_value)
17
+ history.search(source_value) unless source_value.nil? || source_value == ""
18
+ end
19
+
20
+ # @param [String] source_value
21
+ # @param [String] value
22
+ def store_history(source_value, value)
23
+ unless source_value.nil? || source_value == ""
24
+ history.insert(source_value, value)
25
+ end
26
+ end
27
+
28
+ def reset_history
29
+ history.reset
30
+ end
31
+ alias clear_history reset_history
32
+
33
+ class HistoryCache
34
+ include Database
35
+ include Singleton
36
+
37
+ attr_accessor :count
38
+
39
+ def initialize
40
+ @count = 0
41
+
42
+ init_cache
43
+ end
44
+
45
+ # @return [String]
46
+ def search(source_value, _named_range: nil, _column: nil)
47
+ database_service.find_translation(source_value)
48
+ end
49
+
50
+ def insert(source_value, value, named_range: nil, column: nil)
51
+ @count += 1
52
+
53
+ database_service.insert_row(:translations, [
54
+ @count, source_value, value, named_range, column
55
+ ])
56
+ end
57
+
58
+ def all_values
59
+ database_service.all_translations
60
+ end
61
+
62
+ def reset
63
+ @count = 0
64
+ if database_service.table_exist?(:translations)
65
+ database_service.truncate_table(:translations)
66
+ else
67
+ init_cache
68
+ end
69
+ end
70
+
71
+ def table_count
72
+ database_service.table_count(:translations)
73
+ end
74
+
75
+ def init_cache
76
+ return if database_service.table_exist?(:translations)
77
+
78
+ database_service.create_table(:translations, %w[source_value value named_range column])
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+ require "cure/strategy/end_with_strategy"
5
+ require "cure/strategy/full_strategy"
6
+ require "cure/strategy/match_strategy"
7
+ require "cure/strategy/regex_strategy"
8
+ require "cure/strategy/split_strategy"
9
+ require "cure/strategy/start_with_strategy"
10
+ require "cure/strategy/append_strategy"
11
+ require "cure/strategy/prepend_strategy"
12
+ require "cure/strategy/contain_strategy"
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class MatchStrategy < BaseStrategy
8
+ # Additional details needed to make substitution.
9
+ # @return [MatchStrategyParams]
10
+ attr_accessor :params
11
+
12
+ def initialize(options)
13
+ super(MatchStrategyParams.new(options))
14
+ end
15
+
16
+ # gsub catchment group
17
+ # @param [String] source_value
18
+ def _retrieve_value(source_value)
19
+ @params.match || nil if source_value.include? @params.match
20
+ end
21
+
22
+ # @param [String] source_value
23
+ # @param [String] generated_value
24
+ # @return [String]
25
+ def _replace_value(source_value, generated_value)
26
+ return source_value unless source_value.include? @params.match
27
+
28
+ source_value.gsub(@params.match, generated_value)
29
+ end
30
+
31
+ def _describe
32
+ "Match replacement will look for the presence of '#{@params.match}', and replace that value. " \
33
+ "[Note: If the value does not include '#{@params.match}', no substitution is made.]"
34
+ end
35
+ end
36
+
37
+ class MatchStrategyParams < BaseStrategyParams
38
+ attr_reader :match
39
+
40
+ validates :match
41
+
42
+ def initialize(options=nil)
43
+ @match = options[:match]
44
+ super(options)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class PrependStrategy < BaseStrategy
8
+ private
9
+
10
+ # @param [String] source_value
11
+ # @return [String]
12
+ def _retrieve_value(source_value)
13
+ source_value
14
+ end
15
+
16
+ # @param [String] source_value
17
+ # @param [String] generated_value
18
+ # @return [String]
19
+ def _replace_value(source_value, generated_value)
20
+ generated_value + source_value
21
+ end
22
+
23
+ def _describe
24
+ "Prepend generated value to the end of source value"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class RegexStrategy < BaseStrategy
8
+ # Additional details needed to make substitution.
9
+ # @return [RegexStrategyParams]
10
+ attr_accessor :params
11
+
12
+ def initialize(options)
13
+ super(RegexStrategyParams.new(options))
14
+ end
15
+
16
+ # gsub catchment group
17
+ # @param [String] source_value
18
+ def _retrieve_value(source_value)
19
+ m = /#{@params.regex_cg}/.match(source_value)
20
+ return unless m.instance_of?(MatchData) && (!m[1].nil? && m[1] != "")
21
+
22
+ m[1]
23
+ end
24
+
25
+ # @param [String] source_value
26
+ # @param [String] generated_value
27
+ # @return [String]
28
+ def _replace_value(source_value, generated_value)
29
+ m = /#{@params.regex_cg}/.match(source_value)
30
+ return unless m.instance_of?(MatchData) && (!m[1].nil? && m[1] != "")
31
+
32
+ generated_value unless replace_partial_record
33
+
34
+ source_value.gsub(m[1], generated_value)
35
+ end
36
+
37
+ def _describe
38
+ "Matching on '#{@params.regex_cg}'. " \
39
+ "[Note: If the regex does not match, or has no capture group, no substitution is made.]"
40
+ end
41
+
42
+ end
43
+
44
+ class RegexStrategyParams < BaseStrategyParams
45
+ attr_reader :regex_cg
46
+
47
+ validates :regex_cg
48
+
49
+ def initialize(options=nil)
50
+ @regex_cg = options[:regex_cg]
51
+ super(options)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/strategy/base_strategy"
4
+
5
+ module Cure
6
+ module Strategy
7
+ class SplitStrategy < BaseStrategy
8
+ # Additional details needed to make substitution.
9
+ # @return [SplitStrategyParams]
10
+ attr_accessor :params
11
+
12
+ def initialize(options)
13
+ super(SplitStrategyParams.new(options))
14
+ end
15
+
16
+ # @param [String] source_value
17
+ def _retrieve_value(source_value)
18
+ return unless source_value.include?(@params.token)
19
+
20
+ result_arr = source_value.split(@params.token)
21
+ result_arr[@params.index]
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
+ split_token = @params.token
29
+
30
+ return unless source_value.include?(split_token)
31
+
32
+ result_arr = source_value.split(split_token)
33
+ result_arr[@params.index] = generated_value if value?(result_arr[@params.index])
34
+ result_arr.join(split_token)
35
+ end
36
+
37
+ def _describe
38
+ "Splitting on '#{@params.token}', at index #{@params.index}) " \
39
+ "[Note: If the value does not include '#{@params.token}', no substitution is made.]"
40
+ end
41
+ end
42
+
43
+ class SplitStrategyParams < BaseStrategyParams
44
+ attr_reader :token, :index
45
+
46
+ validates :token, validator: :presence
47
+ validates :index, validator: :presence
48
+
49
+ def initialize(options=nil)
50
+ @token = options[:token]
51
+ @index = options[:index]
52
+ # valid?
53
+
54
+ super(options)
55
+ end
56
+ end
57
+ end
58
+ end