k_domain 0.0.2 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
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