k_domain 0.0.2 → 0.0.15

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +39 -1
  3. data/Gemfile +10 -0
  4. data/Rakefile +3 -1
  5. data/STORIES.md +21 -2
  6. data/k_domain.gemspec +4 -0
  7. data/lib/k_domain/domain_model/load.rb +35 -0
  8. data/lib/k_domain/domain_model/transform.rb +110 -0
  9. data/lib/k_domain/domain_model/transform_steps/_.rb +10 -0
  10. data/lib/k_domain/domain_model/transform_steps/step.rb +142 -0
  11. data/lib/k_domain/domain_model/transform_steps/step1_attach_db_schema.rb +21 -0
  12. data/lib/k_domain/domain_model/transform_steps/step2_attach_models.rb +62 -0
  13. data/lib/k_domain/domain_model/transform_steps/step3_attach_columns.rb +137 -0
  14. data/lib/k_domain/domain_model/transform_steps/step4_attach_erd_files.rb +456 -0
  15. data/lib/k_domain/domain_model/transform_steps/step5_attach_dictionary.rb +58 -0
  16. data/lib/k_domain/domain_model/transform_steps/step8_locate_rails_models.rb +44 -0
  17. data/lib/k_domain/raw_db_schema/load.rb +35 -0
  18. data/lib/k_domain/{raw_schema → raw_db_schema}/transform.rb +36 -21
  19. data/lib/k_domain/schemas/_.rb +15 -0
  20. data/lib/k_domain/schemas/database/_.rb +7 -0
  21. data/lib/k_domain/schemas/database/foreign_key.rb +14 -0
  22. data/lib/k_domain/schemas/database/index.rb +14 -0
  23. data/lib/k_domain/schemas/database/schema.rb +31 -0
  24. data/lib/k_domain/schemas/database/table.rb +32 -0
  25. data/lib/k_domain/schemas/dictionary.rb +19 -0
  26. data/lib/k_domain/schemas/domain/_.rb +65 -0
  27. data/lib/k_domain/schemas/domain/domain.rb +11 -0
  28. data/lib/k_domain/schemas/domain/erd_file.rb +80 -0
  29. data/lib/k_domain/schemas/domain/models/column.rb +49 -0
  30. data/lib/k_domain/schemas/domain/models/model.rb +111 -0
  31. data/lib/k_domain/schemas/domain/old/belongs_to.rb +25 -0
  32. data/lib/k_domain/schemas/domain/old/column_old.rb +225 -0
  33. data/lib/k_domain/schemas/domain/old/domain_statistics.rb +29 -0
  34. data/lib/k_domain/schemas/domain/old/entity.rb +338 -0
  35. data/lib/k_domain/schemas/domain/old/entity_statistics.rb +22 -0
  36. data/lib/k_domain/schemas/domain/old/foreign_key.rb +17 -0
  37. data/lib/k_domain/schemas/domain/old/has_and_belongs_to_many.rb +20 -0
  38. data/lib/k_domain/schemas/domain/old/has_many.rb +27 -0
  39. data/lib/k_domain/schemas/domain/old/has_one.rb +41 -0
  40. data/lib/k_domain/schemas/domain/old/name_options.rb +10 -0
  41. data/lib/k_domain/schemas/domain/old/rails_controller.rb +10 -0
  42. data/lib/k_domain/schemas/domain/old/rails_model.rb +92 -0
  43. data/lib/k_domain/schemas/domain/old/related_entity.rb +36 -0
  44. data/lib/k_domain/schemas/domain/old/statistics.rb +21 -0
  45. data/lib/k_domain/schemas/domain/old/validate.rb +25 -0
  46. data/lib/k_domain/schemas/domain/old/validates.rb +50 -0
  47. data/lib/k_domain/schemas/domain_model.rb +14 -0
  48. data/lib/k_domain/schemas/investigate.rb +15 -0
  49. data/lib/k_domain/schemas/rails_resource.rb +16 -0
  50. data/lib/k_domain/version.rb +1 -1
  51. data/lib/k_domain.rb +23 -1
  52. data/{lib/k_domain/raw_schema/template.rb → templates/load_schema.rb} +4 -4
  53. metadata +88 -4
@@ -0,0 +1,456 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Attach source code found in rails model definitions to models
4
+ class Step4AttachErdFiles < KDomain::DomainModel::Step
5
+ attr_accessor :ruby_code
6
+
7
+ # NOTE: This code could be rewritten using monkey patched modules and peak
8
+ def call
9
+ domain[:erd_files] = domain_models.map { |model| load_dsl(model) }
10
+ end
11
+
12
+ private
13
+
14
+ def reset_dsl
15
+ @ruby_code = nil
16
+ @dsl = nil
17
+ end
18
+
19
+ def dsl
20
+ @dsl ||= {
21
+ name: '',
22
+ name_plural: ''
23
+ }
24
+ end
25
+
26
+ def load_dsl(model)
27
+ print '.'
28
+
29
+ reset_dsl
30
+
31
+ dsl[:name] = model[:name]
32
+ dsl[:name_plural] = model[:name_plural]
33
+ dsl[:dsl_file] = model[:erd_location][:exist] ? model[:erd_location][:file] : ''
34
+
35
+ return dsl unless File.exist?(dsl[:dsl_file])
36
+
37
+ @ruby_code = File.read(dsl[:dsl_file])
38
+
39
+ dsl[:source] = read_dsl_source
40
+ dsl[:dsl] = build_dsl
41
+ dsl[:todo] = todo
42
+
43
+ dsl
44
+ end
45
+
46
+ def read_dsl_source
47
+ regex_split_private_public = /(?<public>.+?)(?=\bprivate\b)(?<private>.*)/m
48
+
49
+ split_code = regex_split_private_public.match(ruby_code)
50
+
51
+ public_code = nil
52
+ private_code = nil
53
+
54
+ if split_code
55
+ public_code = split_code[:public]
56
+ private_code = split_code[:private]
57
+ end
58
+
59
+ {
60
+ ruby: ruby_code,
61
+ public: public_code,
62
+ private: private_code,
63
+ all_methods: grab_methods(public_code, private_code)
64
+ }
65
+ end
66
+
67
+ def build_dsl
68
+ return if ruby_code.nil?
69
+
70
+ # need to support options as hash instead of options as string in the future
71
+ {
72
+ default_scope: grab_default_scope,
73
+ scopes: grab_scopes,
74
+ belongs_to: grab_belongs_to,
75
+ has_one: grab_has_one,
76
+ has_many: grab_has_many,
77
+ has_and_belongs_to_many: grab_has_and_belongs_to_many,
78
+ validate_on: grab_validate,
79
+ validates_on: grab_validates
80
+ }
81
+
82
+ # ^(?<spaces>\s*)(?<event_type>before_create|before_save|before_destroy|after_create|after_save|after_destroy) (:(?<name>\w*)[, ]?(?<scope>.*)|(?<scope>\{.*?\}.*$))
83
+ end
84
+
85
+ def grab_default_scope
86
+ regex = /default_scope \{(?<scope>.*?)\}/m
87
+
88
+ m = regex.match(ruby_code)
89
+
90
+ return "{ #{m[:scope].strip.gsub('\n', '')} }" if m
91
+
92
+ nil
93
+ end
94
+
95
+ def grab_scopes
96
+ entries = []
97
+ # Start from beginning of line and capture
98
+ # - number of spaces scope
99
+ # - name of scope
100
+ # - value of scope to end of line
101
+ regex = /^(?<spaces>\s*)scope :(?<name>\w*)[, ]?(?<scope>.*)/
102
+
103
+ # rubocop:disable Metrics/BlockLength
104
+ ruby_code.scan(regex) do
105
+ m = $LAST_MATCH_INFO
106
+ spaces = m[:spaces] # .delete("\n")
107
+ last_lf = spaces.rindex("\n")
108
+ spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
109
+ name = m[:name]
110
+ scope = m[:scope].strip
111
+
112
+ # Found a valid one liner
113
+ if scope.ends_with?('}') && (scope.scan(/{/).count == scope.scan(/}/).count)
114
+ scope = escape_single_quote(scope)
115
+ entries << { name: name, scope: scope }
116
+ else
117
+ # Have a multiline scope, lets see if it is cleanly formatted
118
+
119
+ start_anchor = "#{spaces}scope :#{name}"
120
+ end_anchor = "#{spaces}}"
121
+
122
+ # log.kv 'spaces', spaces.length
123
+ # log.kv 'name', name
124
+ # log.kv 'start_anchor', start_anchor
125
+ # log.kv 'end_anchor', end_anchor
126
+
127
+ start_index = ruby_code.index(/#{start_anchor}/)
128
+
129
+ if start_index.nil?
130
+ log.error("[#{@current_entity[:name]}] could not find [start] anchor index for [#{name}]")
131
+ else
132
+ ruby_section = ruby_code[start_index..-1]
133
+ end_index = ruby_section.index(/^#{end_anchor}/) # Add ^ start of line
134
+ if end_index.nil?
135
+ log.error("[#{@current_entity[:name]}] could not find [end] anchor index for [#{name}]")
136
+ else
137
+ scope = ruby_section[start_anchor.length + 1..end_index].strip
138
+ scope = escape_single_quote("#{scope}#{end_anchor}")
139
+ entries << { name: name, scope: scope }
140
+ end
141
+ end
142
+ end
143
+ end
144
+ entries
145
+ rescue StandardError => e
146
+ # bin ding.pry
147
+ puts e.message
148
+ end
149
+ # rubocop:enable Metrics/BlockLength
150
+
151
+ def grab_belongs_to
152
+ entries = []
153
+
154
+ # Start from beginning of line and capture
155
+ # - number of spaces before belongs_to
156
+ # - name of the belongs_to
157
+ # - value of belongs_to to end of line
158
+ regex = /^(?<spaces>\s*)belongs_to :(?<name>\w*)[, ]?(?<options>.*)/
159
+
160
+ ruby_code.scan(regex) do
161
+ m = $LAST_MATCH_INFO
162
+
163
+ # spaces = m[:spaces] # .delete("\n")
164
+ # last_lf = spaces.rindex("\n")
165
+ # spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
166
+ name = m[:name]
167
+
168
+ options = m[:options]
169
+ .gsub(':polymorphic => ', 'polymorphic: ')
170
+ .gsub(':class_name => ', 'class_name: ')
171
+ .gsub(':foreign_key => ', 'foreign_key: ')
172
+ .strip
173
+
174
+ options = clean_lambda(options)
175
+
176
+ entries << { name: name, options: extract_options(options), raw_options: options }
177
+ end
178
+ entries
179
+ rescue StandardError => e
180
+ # bin ding.pry
181
+ puts e.message
182
+ end
183
+
184
+ def grab_has_one
185
+ entries = []
186
+
187
+ # Start from beginning of line and capture
188
+ # - number of spaces before has_one
189
+ # - name of the has_one
190
+ # - value of has_one to end of line
191
+ regex = /^(?<spaces>\s*)has_one :(?<name>\w*)[, ]?(?<options>.*)/
192
+
193
+ ruby_code.scan(regex) do
194
+ m = $LAST_MATCH_INFO
195
+
196
+ # spaces = m[:spaces] # .delete("\n")
197
+ # last_lf = spaces.rindex("\n")
198
+ # spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
199
+ name = m[:name]
200
+ options = m[:options]
201
+ .strip
202
+ # .gsub(':polymorphic => ', 'polymorphic: ')
203
+ # .gsub(':class_name => ', 'class_name: ')
204
+ # .gsub(':foreign_key => ', 'foreign_key: ')
205
+
206
+ options = clean_lambda(options)
207
+
208
+ entries << { name: name, options: extract_options(options), raw_options: options }
209
+ end
210
+ entries
211
+ rescue StandardError => e
212
+ # bin ding.pry
213
+ puts e.message
214
+ end
215
+
216
+ def grab_has_many
217
+ entries = []
218
+ # Start from beginning of line and capture
219
+ # - number of spaces before has_many
220
+ # - name of the has_many
221
+ # - value of has_many to end of line
222
+ regex = /^(?<spaces>\s*)has_many :(?<name>\w*)[, ]?(?<options>.*)/
223
+
224
+ ruby_code.scan(regex) do
225
+ m = $LAST_MATCH_INFO
226
+
227
+ # spaces = m[:spaces] # .delete("\n")
228
+ # last_lf = spaces.rindex("\n")
229
+ # spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
230
+ name = m[:name]
231
+ options = m[:options]
232
+ .gsub(':dependent => ', 'dependent: ')
233
+ .gsub(':class_name => ', 'class_name: ')
234
+ .gsub(':foreign_key => ', 'foreign_key: ')
235
+ .gsub(':primary_key => ', 'primary_key: ')
236
+ .strip
237
+
238
+ options = clean_lambda(options)
239
+
240
+ entries << { name: name, options: extract_options(options), raw_options: options }
241
+ end
242
+ entries
243
+ rescue StandardError => e
244
+ # bin ding.pry
245
+ puts e.message
246
+ end
247
+
248
+ def grab_has_and_belongs_to_many
249
+ entries = []
250
+ # Start from beginning of line and capture
251
+ # - number of spaces before has_and_belongs_to_many
252
+ # - name of the has_and_belongs_to_many
253
+ # - value of has_and_belongs_to_many to end of line
254
+ regex = /^(?<spaces>\s*)has_and_belongs_to_many :(?<name>\w*)[, ]?(?<options>.*)/
255
+
256
+ ruby_code.scan(regex) do
257
+ m = $LAST_MATCH_INFO
258
+
259
+ # spaces = m[:spaces] # .delete("\n")
260
+ # last_lf = spaces.rindex("\n")
261
+ # spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
262
+ name = m[:name]
263
+ options = m[:options]
264
+ .gsub(':dependent => ', 'dependent: ')
265
+ .gsub(':class_name => ', 'class_name: ')
266
+ .gsub(':foreign_key => ', 'foreign_key: ')
267
+ .gsub(':primary_key => ', 'primary_key: ')
268
+ .strip
269
+
270
+ options = clean_lambda(options)
271
+
272
+ entries << { name: name, options: {}, raw_options: options }
273
+ end
274
+ entries
275
+ rescue StandardError => e
276
+ # bin ding.pry
277
+ puts e.message
278
+ end
279
+
280
+ def grab_validates
281
+ entries = []
282
+ # Start from beginning of line and capture
283
+ # - number of spaces before validates
284
+ # - name of the validates
285
+ # - value of validates to end of line
286
+ regex = /^(?<spaces>\s*)validates :(?<name>\w*)[, ]?(?<options>.*)/
287
+
288
+ ruby_code.scan(regex) do
289
+ m = $LAST_MATCH_INFO
290
+
291
+ # spaces = m[:spaces] # .delete("\n")
292
+ # last_lf = spaces.rindex("\n")
293
+ # spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
294
+ name = m[:name]
295
+
296
+ options = m[:options].strip
297
+
298
+ options = clean_lambda(options)
299
+
300
+ entries << { name: name, raw_options: options }
301
+ end
302
+ entries
303
+ rescue StandardError => e
304
+ # bin ding.pry
305
+ puts e.message
306
+ end
307
+
308
+ def grab_validate
309
+ entries = []
310
+ # Start from beginning of line and capture
311
+ # - number of spaces before validate
312
+ # - list of methods to call until to end of line
313
+ # regex = /^(?<spaces>\s*)validate :(?<name>\w*)[, ]?(?<options>.*)/
314
+ regex = /^(?<spaces>\s*)validate (?<line>:.*)/
315
+ # puts @current_entity[:name]
316
+
317
+ ruby_code.scan(regex) do
318
+ m = $LAST_MATCH_INFO
319
+
320
+ # spaces = m[:spaces] # .delete("\n")
321
+ # last_lf = spaces.rindex("\n")
322
+ # spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
323
+ line = m[:line]
324
+
325
+ entries << { line: line }
326
+ # puts @current_entity[:validate]
327
+ end
328
+ entries
329
+ rescue StandardError => e
330
+ # bin ding.pry
331
+ puts e.message
332
+ end
333
+
334
+ def grab_methods(public_code = ruby_code, private_code = nil)
335
+ # public_code = ruby_code_public.nil? ? ruby_code : ruby_code_public
336
+ # private_code = ruby_code_private
337
+
338
+ regex = /def (?<method>.*)/
339
+
340
+ # log.info(@current_entity[:name])
341
+
342
+ public_methods = parse_methods(:public, public_code&.scan(regex)&.flatten || [])
343
+ private_methods = parse_methods(:private, private_code&.scan(regex)&.flatten || [])
344
+ methods = (public_methods + private_methods)
345
+
346
+ class_methods = methods.select { |method| method[:class_method] == true }
347
+
348
+ all_instance = methods.select { |method| method[:class_method] == false }
349
+ instance_public = all_instance.select { |method| method[:scope] == :public }
350
+ instance_private = all_instance.select { |method| method[:scope] == :private }
351
+
352
+ {
353
+ klass: class_methods,
354
+ instance: all_instance,
355
+ instance_public: instance_public,
356
+ instance_private: instance_private
357
+ }
358
+ end
359
+
360
+ def parse_methods(scope, methods)
361
+ methods.map do |value|
362
+ class_method = value.starts_with?('self.')
363
+ name = class_method ? value[5..-1] : value
364
+ arguments = nil
365
+ arguments_index = name.index('(')
366
+
367
+ if arguments_index
368
+ arguments = name[arguments_index..-1]
369
+ name = name[0..arguments_index - 1]
370
+ end
371
+
372
+ arguments = escape_single_quote(arguments)
373
+
374
+ {
375
+ name: name,
376
+ scope: scope,
377
+ class_method: class_method,
378
+ arguments: arguments&.strip.to_s
379
+ }
380
+ end
381
+ end
382
+
383
+ def todo
384
+ {
385
+ after_destroy: [], # to do
386
+ before_save: [], # to do
387
+ after_save: [], # to do
388
+ before_create: [], # to do
389
+ after_create: [], # to do
390
+ enum: [], # to do
391
+ attr_encrypted: [], # to do
392
+ validates_uniqueness_of: [], # to do
393
+ validates_confirmation_of: [], # to do
394
+ attr_accessor: [], # to do
395
+ attr_reader: [], # to do
396
+ attr_writer: [] # to do
397
+ }
398
+ end
399
+
400
+ def escape_single_quote(value)
401
+ return nil if value.nil?
402
+
403
+ value.gsub("'", "\\\\'")
404
+ end
405
+
406
+ # rubocop:disable Style/EvalWithLocation, Security/Eval, Style/DocumentDynamicEvalDefinition
407
+ def extract_options(options)
408
+ eval("{ #{options} }")
409
+ rescue StandardError => e
410
+ investigate(
411
+ step: :step4_attach_erd_files_models,
412
+ location: :extract_options,
413
+ key: nil,
414
+ message: e.message
415
+ )
416
+ {}
417
+ rescue SyntaxError => e
418
+ # may be the issue is from a comment at the off the line
419
+ comment_index = options.rindex('#') - 1
420
+
421
+ if comment_index.positive?
422
+ options_minus_comment = options[0..comment_index].squish
423
+ return extract_options(options_minus_comment)
424
+ end
425
+
426
+ investigate(
427
+ step: :step4_attach_erd_files_models,
428
+ location: :extract_options,
429
+ key: nil,
430
+ message: e.message
431
+ )
432
+ {}
433
+ end
434
+ # rubocop:enable Style/EvalWithLocation, Security/Eval, Style/DocumentDynamicEvalDefinition
435
+
436
+ def clean_lambda(options)
437
+ if /^->/.match?(options)
438
+ index = options.index(/}\s*,/)
439
+ if index.nil?
440
+ if options.count('{') == options.count('}')
441
+ index = options.rindex(/}/)
442
+ options = "a_lambda: '#{escape_single_quote(options[0..index])}'"
443
+ else
444
+ log.error(options)
445
+ options = "a_lambda: '#{escape_single_quote(options)}'"
446
+ end
447
+ else
448
+ options = "a_lambda: '#{escape_single_quote(options[0..index])}', #{options[index + 2..-1]}"
449
+ end
450
+ end
451
+ options
452
+ rescue StandardError => e
453
+ # bin ding.pry
454
+ puts e.message
455
+ end
456
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Attach data dictionary
4
+ class Step5AttachDictionary < KDomain::DomainModel::Step
5
+ attr_reader :dictionary
6
+
7
+ def call
8
+ @dictionary = {}
9
+
10
+ domain_models.each do |model|
11
+ model[:columns].each do |column|
12
+ process(model[:name], column[:name], column[:type])
13
+ end
14
+ end
15
+
16
+ domain_data[:dictionary] = {
17
+ items: dictionary.values
18
+ }
19
+ end
20
+
21
+ private
22
+
23
+ def process(model_name, column_name, column_type)
24
+ if dictionary.key?(column_name)
25
+ entry = dictionary[column_name]
26
+ entry[:models] << model_name
27
+ entry[:model_count] = entry[:model_count] + 1
28
+
29
+ unless entry[:types].include?(column_type)
30
+ log.warn("#{model_name} has a type mismatch for column name: #{column_name}")
31
+ entry[:types] << column_type
32
+ entry[:type_count] = entry[:type_count] + 1
33
+ end
34
+ return
35
+ end
36
+
37
+ dictionary[column_name] = {
38
+ name: column_name,
39
+ type: column_type,
40
+ label: column_name.to_s.titleize,
41
+ segment: segment(column_name, column_type),
42
+ models: [model_name],
43
+ model_count: 1,
44
+ types: [column_type],
45
+ type_count: 1
46
+ }
47
+ rescue StandardError => e
48
+ log.error e.message
49
+ end
50
+
51
+ def segment(column_name, column_type)
52
+ n = column_name.to_s
53
+ return column_type == :integer ? :id : :id_variant if n.ends_with?('_id')
54
+ return column_type == :datetime ? :stamp : :stamp_variant if n == 'created_at'
55
+
56
+ :data
57
+ end
58
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Locate rails model files
4
+ class Step8LocateRailsModels < KDomain::DomainModel::Step
5
+ attr_accessor :ruby_code
6
+
7
+ def call
8
+ raise 'ERD path not supplied' if opts[:erd_path].nil?
9
+
10
+ self.rails_resource_models = domain_models.map do |model|
11
+ locate_rails_model(model[:name], model[:table_name])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def locate_rails_model(model_name, table_name)
18
+ file_normal = File.join(opts[:erd_path], "#{model_name}.rb")
19
+ file_custom = File.join(opts[:erd_path], "#{table_name}.rb")
20
+ file_exist = true
21
+ state = []
22
+
23
+ if File.exist?(file_normal)
24
+ file = file_normal
25
+ state.push(:has_ruby_model)
26
+ elsif File.exist?(file_custom)
27
+ file = file_custom
28
+ state.push(:has_ruby_model)
29
+ state.push(:non_conventional_name)
30
+ else
31
+ file = ''
32
+ file_exist = false
33
+ state.push(:model_not_found)
34
+ end
35
+
36
+ {
37
+ model_name: model_name,
38
+ table_name: table_name,
39
+ file: file,
40
+ exist: file_exist,
41
+ state: state.join(', ')
42
+ }
43
+ end
44
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Annotates the original schema with methods that implement existing method calls
4
+ # that are already in the schema so that we can build a hash.
5
+ #
6
+ # Writes a new annotated schema.rb file with a public method called load that
7
+ # builds the hash
8
+
9
+ module KDomain
10
+ module RawDbSchema
11
+ class Load
12
+ include KLog::Logging
13
+
14
+ attr_reader :source_file
15
+ attr_reader :data
16
+
17
+ def initialize(source_file)
18
+ @source_file = source_file
19
+ end
20
+
21
+ def call
22
+ json = File.read(source_file)
23
+ @raw_data = KUtil.data.json_parse(json, as: :hash_symbolized)
24
+
25
+ @data = KDomain::Database::Schema.new(@raw_data)
26
+ end
27
+
28
+ def to_h
29
+ return nil unless defined? @raw_data
30
+
31
+ @raw_data
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,67 +1,82 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Annotates the original schema with methods that implement existing method calls
2
4
  # that are already in the schema so that we can build a hash.
3
5
  #
4
6
  # Writes a new annotated schema.rb file with a public method called load that
5
7
  # builds the hash
6
- # frozen_string_literal: true
7
-
8
8
  module KDomain
9
- module RawSchema
9
+ module RawDbSchema
10
10
  class Transform
11
11
  include KLog::Logging
12
12
 
13
13
  attr_reader :source_file
14
14
  attr_reader :template_file
15
- attr_reader :target_ruby_class
16
-
17
- def initialize(source_file)#, target_file)
15
+ attr_reader :schema_loader
16
+
17
+ def initialize(source_file)
18
18
  @source_file = source_file
19
- @template_file = 'lib/k_domain/raw_schema/template.rb'
19
+ @template_file = KDomain::Gem.resource('templates/load_schema.rb')
20
20
  end
21
-
21
+
22
22
  def call
23
23
  # log.kv 'source_file', source_file
24
24
  # log.kv 'template_file', template_file
25
25
  # log.kv 'source_file?', File.exist?(source_file)
26
26
  # log.kv 'template_file?', File.exist?(template_file)
27
-
28
27
  log.error "Template not found: #{template_file}" unless File.exist?(template_file)
29
28
 
30
29
  content = File.read(source_file)
31
30
  content
32
31
  .gsub!(/ActiveRecord::Schema.define/, 'load')
33
32
 
34
- lines = content.lines.map { |line| " #{line}" }.join()
33
+ lines = content.lines.map { |line| " #{line}" }.join
35
34
 
36
- @target_ruby_class = File
35
+ @schema_loader = File
37
36
  .read(template_file)
38
37
  .gsub('{{source_file}}', source_file)
39
38
  .gsub('{{rails_schema}}', lines)
40
39
  end
41
40
 
42
- def write_target(target_file)
43
- if target_ruby_class.nil?
41
+ # rename to target_ruby
42
+ # This is an internal ruby structure that is evaluated
43
+ # writing is only needed for debugging purposes
44
+ def write_schema_loader(target_file)
45
+ if schema_loader.nil?
44
46
  puts '.call method has not been executed'
45
47
  return
46
48
  end
47
49
 
48
50
  FileUtils.mkdir_p(File.dirname(target_file))
49
- File.write(target_file, target_ruby_class)
51
+ File.write(target_file, schema_loader)
50
52
  end
51
53
 
52
- def json
53
- if target_ruby_class.nil?
54
+ def write_json(json_file)
55
+ if schema_loader.nil?
54
56
  puts '.call method has not been executed'
55
57
  return
56
58
  end
57
59
 
58
- # load target_file
59
- eval target_ruby_class
60
-
60
+ FileUtils.mkdir_p(File.dirname(json_file))
61
+ File.write(json_file, JSON.pretty_generate(schema))
62
+ end
63
+
64
+ # rubocop:disable Security/Eval
65
+ def schema
66
+ if schema_loader.nil?
67
+ puts '.call method has not been executed'
68
+ return
69
+ end
70
+
71
+ eval(schema_loader)#, __FILE__, __LINE__)
72
+
61
73
  loader = LoadSchema.new
62
- loader.load_schema()
63
- loader.schema
74
+ loader.load_schema
75
+ return loader.schema
76
+ rescue => ex
77
+ log.exception(ex)
64
78
  end
79
+ # rubocop:enable Security/Eval
65
80
  end
66
81
  end
67
82
  end