k_domain 0.0.16 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/STORIES.md +35 -6
- data/lib/k_domain/domain_model/transform.rb +11 -49
- data/lib/k_domain/domain_model/transform_steps/_.rb +3 -4
- data/lib/k_domain/domain_model/transform_steps/step.rb +7 -1
- data/lib/k_domain/domain_model/transform_steps/{step8_rails_resource_models.rb → step4_rails_resource_models.rb} +1 -1
- data/lib/k_domain/domain_model/transform_steps/step5_rails_models.rb +71 -0
- data/lib/k_domain/domain_model/transform_steps/{step5_attach_dictionary.rb → step6_attach_dictionary.rb} +6 -3
- data/lib/k_domain/rails_code_extractor/extract_model.rb +43 -6
- data/lib/k_domain/rails_code_extractor/{load_shim.rb → shim_loader.rb} +2 -5
- data/lib/k_domain/schemas/_.rb +1 -0
- data/lib/k_domain/schemas/database/index.rb +1 -1
- data/lib/k_domain/schemas/database/table.rb +7 -7
- data/lib/k_domain/schemas/domain/domain.rb +1 -1
- data/lib/k_domain/schemas/domain_model.rb +6 -5
- data/lib/k_domain/schemas/rails_structure.rb +92 -0
- data/lib/k_domain/version.rb +1 -1
- data/lib/k_domain.rb +2 -2
- data/templates/active_record_shims.rb +27 -14
- metadata +7 -7
- data/lib/k_domain/domain_model/transform_steps/step4_attach_erd_files.rb +0 -457
- data/lib/k_domain/domain_model/transform_steps/step9_rails_structure_models.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de5fc8f220781026dd327f40da53eb3a424ec23f38785be8fddc8f1856970dc1
|
4
|
+
data.tar.gz: 5573e60dc8665ab146e0edeb291ebcd3db6b792180e05e24721df9d519038f86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ecaa0fef7e6d622f18d2dfe53bdddf2c17fa91e1c2796ee7bdddf5044880f742003d8cb6f7bb4007eeab4bd2f0becba6f8f0fb329f58776f807cd200bd4ced9
|
7
|
+
data.tar.gz: 76af19179f670d7e4b18121f031b77e18c366259526530b6623f988c5b3e2985ca3a993441e6caacfb7cb71da6afb05c99803234aa85045facdb2c8f09b1194b
|
data/STORIES.md
CHANGED
@@ -16,25 +16,54 @@ As a Developer, I can customize domain configuration, so that I can have opinion
|
|
16
16
|
|
17
17
|
- Handle traits
|
18
18
|
|
19
|
+
### Tasks next on list
|
20
|
+
|
21
|
+
BUGs in domain_model load
|
22
|
+
|
23
|
+
- spec/k_domain/domain_model/load_spec.rb:135
|
24
|
+
- FIXED: module_name should be empty
|
25
|
+
- FIXED: name mismatch (attr_accessor, attr_reader, attr_writer) in behaviours vs in (attr_accessors, attr_readers, attr_writers) functions
|
26
|
+
- functions - (attr_accessors, attr_readers, attr_writers) are all empty
|
27
|
+
|
28
|
+
External ruby process - ShimLoading and ExtractModel
|
29
|
+
|
30
|
+
- You need a clear memory foot print for shim loading and model extraction, best to run these from inside a new ruby process
|
31
|
+
|
32
|
+
Log Warning to Investigate Issues
|
33
|
+
|
34
|
+
- FIXED: All the logged warnings in k_domain need to turn up in on the investigate issues register
|
35
|
+
- Investigate needs a debug flag that when turned on, will write the issues to the console
|
36
|
+
|
37
|
+
Print progress dot
|
38
|
+
|
39
|
+
- Make this configurable
|
40
|
+
- Decide what steps this should run for
|
41
|
+
- Show step label via configuration
|
42
|
+
|
43
|
+
## Stories and tasks
|
44
|
+
|
45
|
+
### Stories - completed
|
46
|
+
|
19
47
|
As a Developer, I can read native rails model data, so that I can leverage existing rails applications for ERD modeling
|
20
48
|
|
49
|
+
- Proof of concept
|
21
50
|
- Use Meta Programming and re-implement ActiveRecord::Base
|
22
51
|
|
23
|
-
### Tasks
|
52
|
+
### Tasks - completed
|
24
53
|
|
25
54
|
Refactor / Simply
|
26
55
|
|
27
|
-
- Replace complex objects
|
56
|
+
- Replace complex objects with structs for ancillary data structures such as investigate
|
57
|
+
|
58
|
+
Steps to support write methods on base class
|
59
|
+
|
60
|
+
- Simplify lib/k_domain/domain_model/transform.rb
|
28
61
|
|
29
62
|
User acceptance testing
|
30
63
|
|
31
64
|
- Provide sample printers for each data structure to visually check data is loading
|
32
65
|
- Point raw_db_schema loader towards a complex ERD and check how it performs
|
33
66
|
|
34
|
-
## Stories and tasks
|
35
|
-
|
36
|
-
### Tasks - completed
|
37
|
-
|
38
67
|
Setup RubyGems and RubyDoc
|
39
68
|
|
40
69
|
- Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_domain)
|
@@ -23,13 +23,12 @@ module KDomain
|
|
23
23
|
# rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
24
24
|
def call
|
25
25
|
valid = true
|
26
|
-
valid &&=
|
27
|
-
valid &&=
|
28
|
-
valid &&=
|
29
|
-
valid &&=
|
30
|
-
valid &&=
|
31
|
-
valid &&=
|
32
|
-
valid &&= step9
|
26
|
+
valid &&= Step1AttachDbSchema.run(domain_data, db_schema: db_schema, step_file: step_file('1-attach-db-schema'))
|
27
|
+
valid &&= Step2AttachModels.run(domain_data, erd_path: erd_path, step_file: step_file('2-attach-model'))
|
28
|
+
valid &&= Step3AttachColumns.run(domain_data, step_file: step_file('3-attach-columns'))
|
29
|
+
valid &&= Step4RailsResourceModels.run(domain_data, erd_path: erd_path, step_file: step_file('4-rails-resource-models'))
|
30
|
+
valid &&= Step5RailsModels.run(domain_data, erd_path: erd_path, step_file: step_file('5-rails-models'))
|
31
|
+
valid &&= Step6AttachDictionary.run(domain_data, erd_path: erd_path, step_file: step_file('6-attach-dictionary'))
|
33
32
|
|
34
33
|
raise 'DomainModal transform failed' unless valid
|
35
34
|
|
@@ -39,49 +38,13 @@ module KDomain
|
|
39
38
|
end
|
40
39
|
# rubocop:enable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
41
40
|
|
42
|
-
def
|
43
|
-
|
44
|
-
write(step: '1-attach-db-schema')
|
41
|
+
def step_file(step_name)
|
42
|
+
target_step_file % { step: step_name }
|
45
43
|
end
|
46
44
|
|
47
|
-
def
|
48
|
-
|
49
|
-
write(
|
50
|
-
end
|
51
|
-
|
52
|
-
def step3
|
53
|
-
Step3AttachColumns.run(domain_data)
|
54
|
-
write(step: '3-attach-columns')
|
55
|
-
end
|
56
|
-
|
57
|
-
def step4
|
58
|
-
Step4AttachErdFiles.run(domain_data, erd_path: erd_path)
|
59
|
-
write(step: '4-attach-erd-files')
|
60
|
-
end
|
61
|
-
|
62
|
-
def step5
|
63
|
-
Step5AttachDictionary.run(domain_data, erd_path: erd_path)
|
64
|
-
write(step: '5-attach-dictionary')
|
65
|
-
end
|
66
|
-
|
67
|
-
def step8
|
68
|
-
Step8RailsResourceModels.run(domain_data, erd_path: erd_path)
|
69
|
-
write(step: '8-rails-resource-models')
|
70
|
-
end
|
71
|
-
|
72
|
-
def step9
|
73
|
-
Step9RailsStructureModels.run(domain_data, erd_path: erd_path)
|
74
|
-
write(step: '8-rails-structure-models')
|
75
|
-
end
|
76
|
-
|
77
|
-
def write(step: nil)
|
78
|
-
file = if step.nil?
|
79
|
-
target_file
|
80
|
-
else
|
81
|
-
format(target_step_file, step: step)
|
82
|
-
end
|
83
|
-
FileUtils.mkdir_p(File.dirname(file))
|
84
|
-
File.write(file, JSON.pretty_generate(domain_data))
|
45
|
+
def write
|
46
|
+
FileUtils.mkdir_p(File.dirname(target_file))
|
47
|
+
File.write(target_file, JSON.pretty_generate(domain_data))
|
85
48
|
end
|
86
49
|
|
87
50
|
# rubocop:disable Metrics/MethodLength
|
@@ -90,7 +53,6 @@ module KDomain
|
|
90
53
|
@domain_data ||= {
|
91
54
|
domain: {
|
92
55
|
models: [],
|
93
|
-
erd_files: []
|
94
56
|
},
|
95
57
|
rails_resource: {
|
96
58
|
models: [],
|
@@ -5,7 +5,6 @@ require_relative './step'
|
|
5
5
|
require_relative './step1_attach_db_schema'
|
6
6
|
require_relative './step2_attach_models'
|
7
7
|
require_relative './step3_attach_columns'
|
8
|
-
require_relative './
|
9
|
-
require_relative './
|
10
|
-
require_relative './
|
11
|
-
require_relative './step9_rails_structure_models'
|
8
|
+
require_relative './step4_rails_resource_models'
|
9
|
+
require_relative './step5_rails_models'
|
10
|
+
require_relative './step6_attach_dictionary'
|
@@ -24,7 +24,8 @@ module KDomain
|
|
24
24
|
def self.run(domain_data, **opts)
|
25
25
|
step = new(domain_data, **opts)
|
26
26
|
step.call
|
27
|
-
step
|
27
|
+
step.write(opts[:step_file])
|
28
|
+
step.valid?
|
28
29
|
end
|
29
30
|
|
30
31
|
def guard(message)
|
@@ -32,6 +33,11 @@ module KDomain
|
|
32
33
|
@valid = false
|
33
34
|
end
|
34
35
|
|
36
|
+
def write(file)
|
37
|
+
FileUtils.mkdir_p(File.dirname(file))
|
38
|
+
File.write(file, JSON.pretty_generate(domain_data))
|
39
|
+
end
|
40
|
+
|
35
41
|
# Domain Model Accessor/Helpers
|
36
42
|
def domain
|
37
43
|
guard('domain is missing') if domain_data[:domain].nil?
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Locate rails model files
|
4
|
+
class Step5RailsModels < KDomain::DomainModel::Step
|
5
|
+
def call
|
6
|
+
raise 'ERD path not supplied' unless opts[:erd_path]
|
7
|
+
|
8
|
+
self.rails_structure_models = rails_resource_models.map do |resource|
|
9
|
+
process_resource(OpenStruct.new(resource))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def process_resource(resource)
|
16
|
+
@model = {
|
17
|
+
model_name: resource.model_name,
|
18
|
+
table_name: resource.table_name,
|
19
|
+
file: resource.file,
|
20
|
+
exist: resource.exist,
|
21
|
+
state: resource.state,
|
22
|
+
code: resource.exist ? File.read(resource.file) : '',
|
23
|
+
behaviours: {},
|
24
|
+
functions: {}
|
25
|
+
}
|
26
|
+
|
27
|
+
return @model unless resource.exist
|
28
|
+
|
29
|
+
@model[:behaviours] = extract_model_behavior(resource.file)
|
30
|
+
@model[:functions] = extract_model_functions(resource.file)
|
31
|
+
|
32
|
+
@model
|
33
|
+
end
|
34
|
+
|
35
|
+
def extract_model_behavior(file)
|
36
|
+
extractor.extract(file)
|
37
|
+
extractor.model
|
38
|
+
end
|
39
|
+
|
40
|
+
def extract_model_functions(file)
|
41
|
+
klass_name = File.basename(file, File.extname(file))
|
42
|
+
|
43
|
+
klass = case klass_name
|
44
|
+
when 'clearbit_quota'
|
45
|
+
ClearbitQuota
|
46
|
+
when 'account_history_data'
|
47
|
+
AccountHistoryData
|
48
|
+
else
|
49
|
+
Module.const_get(klass_name.classify)
|
50
|
+
end
|
51
|
+
|
52
|
+
class_info = Peeky.api.build_class_info(klass.new)
|
53
|
+
|
54
|
+
class_info.to_h
|
55
|
+
rescue StandardError => e
|
56
|
+
log.exception(e)
|
57
|
+
end
|
58
|
+
|
59
|
+
def extractor
|
60
|
+
@extractor ||= KDomain::RailsCodeExtractor::ExtractModel.new(shim_loader)
|
61
|
+
end
|
62
|
+
|
63
|
+
def shim_loader
|
64
|
+
return opts[:shim_loader] if !opts[:shim_loader].nil? && opts[:shim_loader].is_a?(KDomain::RailsCodeExtractor::ShimLoader)
|
65
|
+
|
66
|
+
shim_loader = KDomain::RailsCodeExtractor::ShimLoader.new
|
67
|
+
shim_loader.register(:fake_module , KDomain::Gem.resource('templates/fake_module_shims.rb'))
|
68
|
+
shim_loader.register(:active_record, KDomain::Gem.resource('templates/active_record_shims.rb'))
|
69
|
+
shim_loader
|
70
|
+
end
|
71
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Attach data dictionary
|
4
|
-
class
|
4
|
+
class Step6AttachDictionary < KDomain::DomainModel::Step
|
5
5
|
attr_reader :dictionary
|
6
6
|
|
7
7
|
def call
|
@@ -27,8 +27,11 @@ class Step5AttachDictionary < KDomain::DomainModel::Step
|
|
27
27
|
entry[:model_count] = entry[:model_count] + 1
|
28
28
|
|
29
29
|
unless entry[:types].include?(column_type)
|
30
|
-
|
31
|
-
|
30
|
+
investigate(step: :step5_attach_dictionary,
|
31
|
+
location: :process,
|
32
|
+
key: "#{model_name},#{column_name},#{column_type}",
|
33
|
+
message: "#{model_name} has a type mismatch for column name: #{column_name}")
|
34
|
+
|
32
35
|
entry[:types] << column_type
|
33
36
|
entry[:type_count] = entry[:type_count] + 1
|
34
37
|
end
|
@@ -6,16 +6,53 @@ module KDomain
|
|
6
6
|
class ExtractModel
|
7
7
|
include KLog::Logging
|
8
8
|
|
9
|
-
attr_reader :
|
10
|
-
attr_reader :
|
9
|
+
attr_reader :shims_loaded
|
10
|
+
attr_reader :models
|
11
|
+
attr_reader :model
|
11
12
|
|
12
|
-
def initialize(
|
13
|
-
@
|
13
|
+
def initialize(load_shim)
|
14
|
+
@load_shim = load_shim
|
15
|
+
@shims_loaded = false
|
16
|
+
@models = []
|
14
17
|
end
|
15
18
|
|
16
|
-
def
|
17
|
-
|
19
|
+
def extract(file)
|
20
|
+
load_shims unless shims_loaded
|
21
|
+
|
22
|
+
ActiveRecord.current_class = nil
|
23
|
+
|
24
|
+
load_retry(file, 10)
|
25
|
+
rescue StandardError => e
|
26
|
+
log.exception(e)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def load_shims
|
32
|
+
@load_shim.call
|
33
|
+
@shims_loaded = true
|
34
|
+
end
|
35
|
+
|
36
|
+
# rubocop:disable Security/Eval,Style/EvalWithLocation,Style/DocumentDynamicEvalDefinition,Metrics/AbcSize
|
37
|
+
def load_retry(file, times)
|
38
|
+
return if times.negative?
|
39
|
+
|
40
|
+
load(file)
|
41
|
+
|
42
|
+
@model = ActiveRecord.current_class
|
43
|
+
@models << @model
|
44
|
+
|
45
|
+
# get_method_info(File.base_name(file))
|
46
|
+
rescue StandardError => e
|
47
|
+
puts e.message
|
48
|
+
if e.is_a?(NameError)
|
49
|
+
log.kv('add module', e.name)
|
50
|
+
eval("module #{e.name}; end")
|
51
|
+
return load_retry(path, times - 1)
|
52
|
+
end
|
53
|
+
log.exception(e)
|
18
54
|
end
|
55
|
+
# rubocop:enable Security/Eval,Style/EvalWithLocation,Style/DocumentDynamicEvalDefinition,Metrics/AbcSize
|
19
56
|
end
|
20
57
|
end
|
21
58
|
end
|
@@ -8,20 +8,17 @@
|
|
8
8
|
# 2. Inject fake module/classes that would otherwise break code loading with various exceptions
|
9
9
|
module KDomain
|
10
10
|
module RailsCodeExtractor
|
11
|
-
class
|
11
|
+
class ShimLoader
|
12
12
|
include KLog::Logging
|
13
13
|
|
14
14
|
attr_reader :shim_files
|
15
15
|
|
16
|
-
attr_reader :dsl_shim_file
|
17
|
-
attr_reader :fake_module_file
|
18
|
-
|
19
16
|
def initialize
|
20
17
|
@shim_files = []
|
21
18
|
end
|
22
19
|
|
23
20
|
def call
|
24
|
-
|
21
|
+
shim_files.select { |sf| sf[:exist] }.each { |sf| require sf[:file] }
|
25
22
|
end
|
26
23
|
|
27
24
|
def register(name, file)
|
data/lib/k_domain/schemas/_.rb
CHANGED
@@ -8,7 +8,7 @@ module KDomain
|
|
8
8
|
attribute :using , Types::Nominal::String
|
9
9
|
attribute :order? , Types::Nominal::Hash
|
10
10
|
attribute :where? , Types::Nominal::Any.optional.default(nil)
|
11
|
-
attribute :unique?
|
11
|
+
attribute :unique? , Types::Nominal::Any.optional.default(nil)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -20,13 +20,13 @@ module KDomain
|
|
20
20
|
attribute :limit? , Types::Strict::Integer.optional.default(nil)
|
21
21
|
end
|
22
22
|
|
23
|
-
attribute :name
|
24
|
-
attribute :primary_key
|
25
|
-
attribute :primary_key_type
|
26
|
-
attribute :id?
|
27
|
-
attribute :columns
|
28
|
-
attribute :indexes
|
29
|
-
attribute :rails_schema
|
23
|
+
attribute :name , Types::Strict::String
|
24
|
+
attribute :primary_key , Types::Strict::String.optional.default(nil)
|
25
|
+
attribute :primary_key_type , Types::Strict::String.optional.default(nil)
|
26
|
+
attribute :id? , Types::Nominal::Any.optional.default(nil)
|
27
|
+
attribute :columns , Types::Strict::Array.of(KDomain::Database::Table::Column)
|
28
|
+
attribute :indexes , Types::Strict::Array.of(KDomain::Database::Index) # May want to have a Table::Index, but for now this is a shared scheam
|
29
|
+
attribute :rails_schema , KDomain::Database::Table::RailsSchema
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -5,7 +5,7 @@ module KDomain
|
|
5
5
|
module DomainModel
|
6
6
|
class Domain < Dry::Struct
|
7
7
|
attribute :models , Types::Strict::Array.of(KDomain::DomainModel::Model)
|
8
|
-
attribute :erd_files , Types::Strict::Array.of(KDomain::DomainModel::ErdFile)
|
8
|
+
# attribute :erd_files , Types::Strict::Array.of(KDomain::DomainModel::ErdFile)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -4,11 +4,12 @@
|
|
4
4
|
module KDomain
|
5
5
|
module Schemas
|
6
6
|
class DomainModel < Dry::Struct
|
7
|
-
attribute :domain
|
8
|
-
attribute :database
|
9
|
-
attribute :dictionary
|
10
|
-
attribute :rails_resource
|
11
|
-
attribute :
|
7
|
+
attribute :domain , KDomain::DomainModel::Domain
|
8
|
+
attribute :database , KDomain::Database::Schema
|
9
|
+
attribute :dictionary , KDomain::Schemas::Dictionary
|
10
|
+
attribute :rails_resource , KDomain::Schemas::RailsResource
|
11
|
+
attribute :rails_structure , KDomain::Schemas::RailsStructure
|
12
|
+
attribute :investigate , KDomain::Schemas::Investigate
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Domain class holds a dictionary entry
|
4
|
+
module KDomain
|
5
|
+
module Schemas
|
6
|
+
class RailsStructure < Dry::Struct
|
7
|
+
class DefaultScope < Dry::Struct
|
8
|
+
attribute :block? , Types::Strict::String
|
9
|
+
end
|
10
|
+
|
11
|
+
class BaseType < Dry::Struct
|
12
|
+
attribute :name? , Types::Strict::String
|
13
|
+
attribute :opts? , Types::Strict::Hash
|
14
|
+
attribute :block? , Types::Strict::String.optional.default(nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
class Scope < KDomain::Schemas::RailsStructure::BaseType
|
18
|
+
end
|
19
|
+
|
20
|
+
class BelongsTo < KDomain::Schemas::RailsStructure::BaseType
|
21
|
+
end
|
22
|
+
|
23
|
+
class HasOne < KDomain::Schemas::RailsStructure::BaseType
|
24
|
+
end
|
25
|
+
|
26
|
+
class HasMany < KDomain::Schemas::RailsStructure::BaseType
|
27
|
+
end
|
28
|
+
|
29
|
+
class HasAndBelongsToMany < KDomain::Schemas::RailsStructure::BaseType
|
30
|
+
end
|
31
|
+
|
32
|
+
class Validate < Dry::Struct
|
33
|
+
attribute :names? , Types::Array.of(Types::Strict::String)
|
34
|
+
attribute :opts? , Types::Strict::Hash
|
35
|
+
attribute :block? , Types::Strict::String.optional.default(nil)
|
36
|
+
end
|
37
|
+
|
38
|
+
class Validates < KDomain::Schemas::RailsStructure::BaseType
|
39
|
+
end
|
40
|
+
|
41
|
+
class Behaviours < Dry::Struct
|
42
|
+
attribute :class_name? , Types::Strict::String
|
43
|
+
attribute :default_scope? , KDomain::Schemas::RailsStructure::DefaultScope
|
44
|
+
attribute :scopes? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Scope)
|
45
|
+
attribute :belongs_to? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::BelongsTo)
|
46
|
+
attribute :has_one? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::HasOne)
|
47
|
+
attribute :has_many? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::HasMany)
|
48
|
+
attribute :has_and_belongs_to_many? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::HasAndBelongsToMany)
|
49
|
+
attribute :validate? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Validate)
|
50
|
+
attribute :validates? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Validates)
|
51
|
+
attribute :attr_accessor? , Types::Array.of(Types::Strict::String)
|
52
|
+
attribute :attr_reader? , Types::Array.of(Types::Strict::String)
|
53
|
+
attribute :attr_writer? , Types::Array.of(Types::Strict::String)
|
54
|
+
end
|
55
|
+
|
56
|
+
class Method < Dry::Struct
|
57
|
+
attribute :name , Types::Strict::String
|
58
|
+
end
|
59
|
+
|
60
|
+
class Functions < Dry::Struct
|
61
|
+
attribute :class_name? , Types::Strict::String
|
62
|
+
attribute :module_name? , Types::Strict::String
|
63
|
+
attribute :class_full_name? , Types::Strict::String
|
64
|
+
attribute :attr_accessor? , Types::Array.of(Types::Strict::String)
|
65
|
+
attribute :attr_reader? , Types::Array.of(Types::Strict::String)
|
66
|
+
attribute :attr_writer? , Types::Array.of(Types::Strict::String)
|
67
|
+
attribute :klass? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Method)
|
68
|
+
attribute :instance_public? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Method)
|
69
|
+
attribute :instance_private? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Method)
|
70
|
+
end
|
71
|
+
|
72
|
+
class Model < Dry::Struct
|
73
|
+
attribute :model_name , Types::Strict::String
|
74
|
+
attribute :table_name , Types::Strict::String
|
75
|
+
attribute :file , Types::Strict::String
|
76
|
+
attribute :exist , Types::Strict::Bool
|
77
|
+
attribute :state , Types::Strict::String
|
78
|
+
attribute :code , Types::Strict::String
|
79
|
+
attribute :behaviours? , KDomain::Schemas::RailsStructure::Behaviours
|
80
|
+
attribute :functions? , KDomain::Schemas::RailsStructure::Functions
|
81
|
+
end
|
82
|
+
|
83
|
+
class Controller < Dry::Struct
|
84
|
+
end
|
85
|
+
|
86
|
+
attribute :models , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Model)
|
87
|
+
attribute :controllers , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Controller)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# attribute :domain , KDomain::DomainModel::Domain
|
data/lib/k_domain/version.rb
CHANGED
data/lib/k_domain.rb
CHANGED
@@ -11,8 +11,8 @@ require 'k_domain/raw_db_schema/load'
|
|
11
11
|
require 'k_domain/domain_model/transform'
|
12
12
|
require 'k_domain/domain_model/transform_steps/_'
|
13
13
|
require 'k_domain/domain_model/load'
|
14
|
-
require 'k_domain/rails_code_extractor/
|
15
|
-
|
14
|
+
require 'k_domain/rails_code_extractor/shim_loader'
|
15
|
+
require 'k_domain/rails_code_extractor/extract_model'
|
16
16
|
|
17
17
|
# # This is useful if you want to initialize structures via Hash
|
18
18
|
# class SymbolizeStruct < Dry::Struct
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
def self.
|
3
|
-
@
|
2
|
+
def self.current_class
|
3
|
+
@current_class ||= nil
|
4
4
|
end
|
5
5
|
|
6
|
-
def self.
|
7
|
-
@
|
6
|
+
def self.current_class=(value)
|
7
|
+
@current_class = value
|
8
8
|
end
|
9
9
|
|
10
10
|
class Base
|
@@ -15,17 +15,11 @@ module ActiveRecord
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.class_info
|
18
|
-
return
|
18
|
+
return ActiveRecord.current_class if ActiveRecord.current_class
|
19
19
|
|
20
|
-
ActiveRecord.
|
21
|
-
|
22
|
-
@class_info = {
|
20
|
+
ActiveRecord.current_class = {
|
23
21
|
class_name: name
|
24
22
|
}
|
25
|
-
|
26
|
-
ActiveRecord.all_loaded_classes << class_info
|
27
|
-
|
28
|
-
@class_info
|
29
23
|
end
|
30
24
|
|
31
25
|
def self.set(key, value)
|
@@ -67,15 +61,36 @@ module ActiveRecord
|
|
67
61
|
add(:enum, opts)
|
68
62
|
end
|
69
63
|
|
64
|
+
# def self.attr_accessor(*args)
|
65
|
+
# args.each do |arg|
|
66
|
+
# self.class_eval("def #{arg};@#{arg};end")
|
67
|
+
# self.class_eval("def #{arg}=(val);@#{arg}=val;end")
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
# def self.attr_reader(*args)
|
71
|
+
# args.each do |arg|
|
72
|
+
# self.class_eval("def #{arg};@#{arg};end")
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
# def self.attr_writer(*args)
|
76
|
+
# args.each do |arg|
|
77
|
+
# self.class_eval("def #{arg};@#{arg};end")
|
78
|
+
# self.class_eval("def #{arg}=(val);@#{arg}=val;end")
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
|
70
82
|
def self.attr_accessor(*names)
|
83
|
+
super(*names)
|
71
84
|
add(:attr_accessor, names)
|
72
85
|
end
|
73
86
|
|
74
87
|
def self.attr_reader(*names)
|
88
|
+
super(*names)
|
75
89
|
add(:attr_reader, names)
|
76
90
|
end
|
77
91
|
|
78
92
|
def self.attr_writer(*names)
|
93
|
+
super(*names)
|
79
94
|
add(:attr_writer, names)
|
80
95
|
end
|
81
96
|
|
@@ -159,8 +174,6 @@ module ActiveRecord
|
|
159
174
|
block_source = nil
|
160
175
|
block_source = lambda_source(block, 'validate') if block_given?
|
161
176
|
|
162
|
-
set(:default_scope, opts.merge(block: block_source))
|
163
|
-
|
164
177
|
add(:validate, {
|
165
178
|
names: names,
|
166
179
|
opts: opts,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: k_domain
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Cruwys
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -102,12 +102,11 @@ files:
|
|
102
102
|
- lib/k_domain/domain_model/transform_steps/step1_attach_db_schema.rb
|
103
103
|
- lib/k_domain/domain_model/transform_steps/step2_attach_models.rb
|
104
104
|
- lib/k_domain/domain_model/transform_steps/step3_attach_columns.rb
|
105
|
-
- lib/k_domain/domain_model/transform_steps/
|
106
|
-
- lib/k_domain/domain_model/transform_steps/
|
107
|
-
- lib/k_domain/domain_model/transform_steps/
|
108
|
-
- lib/k_domain/domain_model/transform_steps/step9_rails_structure_models.rb
|
105
|
+
- lib/k_domain/domain_model/transform_steps/step4_rails_resource_models.rb
|
106
|
+
- lib/k_domain/domain_model/transform_steps/step5_rails_models.rb
|
107
|
+
- lib/k_domain/domain_model/transform_steps/step6_attach_dictionary.rb
|
109
108
|
- lib/k_domain/rails_code_extractor/extract_model.rb
|
110
|
-
- lib/k_domain/rails_code_extractor/
|
109
|
+
- lib/k_domain/rails_code_extractor/shim_loader.rb
|
111
110
|
- lib/k_domain/raw_db_schema/load.rb
|
112
111
|
- lib/k_domain/raw_db_schema/transform.rb
|
113
112
|
- lib/k_domain/schemas/_.rb
|
@@ -141,6 +140,7 @@ files:
|
|
141
140
|
- lib/k_domain/schemas/domain_model.rb
|
142
141
|
- lib/k_domain/schemas/investigate.rb
|
143
142
|
- lib/k_domain/schemas/rails_resource.rb
|
143
|
+
- lib/k_domain/schemas/rails_structure.rb
|
144
144
|
- lib/k_domain/version.rb
|
145
145
|
- templates/active_record_shims.rb
|
146
146
|
- templates/fake_module_shims.rb
|
@@ -1,457 +0,0 @@
|
|
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
|
-
# this should be a configuration
|
28
|
-
# print '.'
|
29
|
-
|
30
|
-
reset_dsl
|
31
|
-
|
32
|
-
dsl[:name] = model[:name]
|
33
|
-
dsl[:name_plural] = model[:name_plural]
|
34
|
-
dsl[:dsl_file] = model[:erd_location][:exist] ? model[:erd_location][:file] : ''
|
35
|
-
|
36
|
-
return dsl unless File.exist?(dsl[:dsl_file])
|
37
|
-
|
38
|
-
@ruby_code = File.read(dsl[:dsl_file])
|
39
|
-
|
40
|
-
dsl[:source] = read_dsl_source
|
41
|
-
dsl[:dsl] = build_dsl
|
42
|
-
dsl[:todo] = todo
|
43
|
-
|
44
|
-
dsl
|
45
|
-
end
|
46
|
-
|
47
|
-
def read_dsl_source
|
48
|
-
regex_split_private_public = /(?<public>.+?)(?=\bprivate\b)(?<private>.*)/m
|
49
|
-
|
50
|
-
split_code = regex_split_private_public.match(ruby_code)
|
51
|
-
|
52
|
-
public_code = nil
|
53
|
-
private_code = nil
|
54
|
-
|
55
|
-
if split_code
|
56
|
-
public_code = split_code[:public]
|
57
|
-
private_code = split_code[:private]
|
58
|
-
end
|
59
|
-
|
60
|
-
{
|
61
|
-
ruby: ruby_code,
|
62
|
-
public: public_code,
|
63
|
-
private: private_code,
|
64
|
-
all_methods: grab_methods(public_code, private_code)
|
65
|
-
}
|
66
|
-
end
|
67
|
-
|
68
|
-
def build_dsl
|
69
|
-
return if ruby_code.nil?
|
70
|
-
|
71
|
-
# need to support options as hash instead of options as string in the future
|
72
|
-
{
|
73
|
-
default_scope: grab_default_scope,
|
74
|
-
scopes: grab_scopes,
|
75
|
-
belongs_to: grab_belongs_to,
|
76
|
-
has_one: grab_has_one,
|
77
|
-
has_many: grab_has_many,
|
78
|
-
has_and_belongs_to_many: grab_has_and_belongs_to_many,
|
79
|
-
validate_on: grab_validate,
|
80
|
-
validates_on: grab_validates
|
81
|
-
}
|
82
|
-
|
83
|
-
# ^(?<spaces>\s*)(?<event_type>before_create|before_save|before_destroy|after_create|after_save|after_destroy) (:(?<name>\w*)[, ]?(?<scope>.*)|(?<scope>\{.*?\}.*$))
|
84
|
-
end
|
85
|
-
|
86
|
-
def grab_default_scope
|
87
|
-
regex = /default_scope \{(?<scope>.*?)\}/m
|
88
|
-
|
89
|
-
m = regex.match(ruby_code)
|
90
|
-
|
91
|
-
return "{ #{m[:scope].strip.gsub('\n', '')} }" if m
|
92
|
-
|
93
|
-
nil
|
94
|
-
end
|
95
|
-
|
96
|
-
def grab_scopes
|
97
|
-
entries = []
|
98
|
-
# Start from beginning of line and capture
|
99
|
-
# - number of spaces scope
|
100
|
-
# - name of scope
|
101
|
-
# - value of scope to end of line
|
102
|
-
regex = /^(?<spaces>\s*)scope :(?<name>\w*)[, ]?(?<scope>.*)/
|
103
|
-
|
104
|
-
# rubocop:disable Metrics/BlockLength
|
105
|
-
ruby_code.scan(regex) do
|
106
|
-
m = $LAST_MATCH_INFO
|
107
|
-
spaces = m[:spaces] # .delete("\n")
|
108
|
-
last_lf = spaces.rindex("\n")
|
109
|
-
spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
|
110
|
-
name = m[:name]
|
111
|
-
scope = m[:scope].strip
|
112
|
-
|
113
|
-
# Found a valid one liner
|
114
|
-
if scope.ends_with?('}') && (scope.scan(/{/).count == scope.scan(/}/).count)
|
115
|
-
scope = escape_single_quote(scope)
|
116
|
-
entries << { name: name, scope: scope }
|
117
|
-
else
|
118
|
-
# Have a multiline scope, lets see if it is cleanly formatted
|
119
|
-
|
120
|
-
start_anchor = "#{spaces}scope :#{name}"
|
121
|
-
end_anchor = "#{spaces}}"
|
122
|
-
|
123
|
-
# log.kv 'spaces', spaces.length
|
124
|
-
# log.kv 'name', name
|
125
|
-
# log.kv 'start_anchor', start_anchor
|
126
|
-
# log.kv 'end_anchor', end_anchor
|
127
|
-
|
128
|
-
start_index = ruby_code.index(/#{start_anchor}/)
|
129
|
-
|
130
|
-
if start_index.nil?
|
131
|
-
log.error("[#{@current_entity[:name]}] could not find [start] anchor index for [#{name}]")
|
132
|
-
else
|
133
|
-
ruby_section = ruby_code[start_index..-1]
|
134
|
-
end_index = ruby_section.index(/^#{end_anchor}/) # Add ^ start of line
|
135
|
-
if end_index.nil?
|
136
|
-
log.error("[#{@current_entity[:name]}] could not find [end] anchor index for [#{name}]")
|
137
|
-
else
|
138
|
-
scope = ruby_section[start_anchor.length + 1..end_index].strip
|
139
|
-
scope = escape_single_quote("#{scope}#{end_anchor}")
|
140
|
-
entries << { name: name, scope: scope }
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
entries
|
146
|
-
rescue StandardError => e
|
147
|
-
# bin ding.pry
|
148
|
-
puts e.message
|
149
|
-
end
|
150
|
-
# rubocop:enable Metrics/BlockLength
|
151
|
-
|
152
|
-
def grab_belongs_to
|
153
|
-
entries = []
|
154
|
-
|
155
|
-
# Start from beginning of line and capture
|
156
|
-
# - number of spaces before belongs_to
|
157
|
-
# - name of the belongs_to
|
158
|
-
# - value of belongs_to to end of line
|
159
|
-
regex = /^(?<spaces>\s*)belongs_to :(?<name>\w*)[, ]?(?<options>.*)/
|
160
|
-
|
161
|
-
ruby_code.scan(regex) do
|
162
|
-
m = $LAST_MATCH_INFO
|
163
|
-
|
164
|
-
# spaces = m[:spaces] # .delete("\n")
|
165
|
-
# last_lf = spaces.rindex("\n")
|
166
|
-
# spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
|
167
|
-
name = m[:name]
|
168
|
-
|
169
|
-
options = m[:options]
|
170
|
-
.gsub(':polymorphic => ', 'polymorphic: ')
|
171
|
-
.gsub(':class_name => ', 'class_name: ')
|
172
|
-
.gsub(':foreign_key => ', 'foreign_key: ')
|
173
|
-
.strip
|
174
|
-
|
175
|
-
options = clean_lambda(options)
|
176
|
-
|
177
|
-
entries << { name: name, options: extract_options(options), raw_options: options }
|
178
|
-
end
|
179
|
-
entries
|
180
|
-
rescue StandardError => e
|
181
|
-
# bin ding.pry
|
182
|
-
puts e.message
|
183
|
-
end
|
184
|
-
|
185
|
-
def grab_has_one
|
186
|
-
entries = []
|
187
|
-
|
188
|
-
# Start from beginning of line and capture
|
189
|
-
# - number of spaces before has_one
|
190
|
-
# - name of the has_one
|
191
|
-
# - value of has_one to end of line
|
192
|
-
regex = /^(?<spaces>\s*)has_one :(?<name>\w*)[, ]?(?<options>.*)/
|
193
|
-
|
194
|
-
ruby_code.scan(regex) do
|
195
|
-
m = $LAST_MATCH_INFO
|
196
|
-
|
197
|
-
# spaces = m[:spaces] # .delete("\n")
|
198
|
-
# last_lf = spaces.rindex("\n")
|
199
|
-
# spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
|
200
|
-
name = m[:name]
|
201
|
-
options = m[:options]
|
202
|
-
.strip
|
203
|
-
# .gsub(':polymorphic => ', 'polymorphic: ')
|
204
|
-
# .gsub(':class_name => ', 'class_name: ')
|
205
|
-
# .gsub(':foreign_key => ', 'foreign_key: ')
|
206
|
-
|
207
|
-
options = clean_lambda(options)
|
208
|
-
|
209
|
-
entries << { name: name, options: extract_options(options), raw_options: options }
|
210
|
-
end
|
211
|
-
entries
|
212
|
-
rescue StandardError => e
|
213
|
-
# bin ding.pry
|
214
|
-
puts e.message
|
215
|
-
end
|
216
|
-
|
217
|
-
def grab_has_many
|
218
|
-
entries = []
|
219
|
-
# Start from beginning of line and capture
|
220
|
-
# - number of spaces before has_many
|
221
|
-
# - name of the has_many
|
222
|
-
# - value of has_many to end of line
|
223
|
-
regex = /^(?<spaces>\s*)has_many :(?<name>\w*)[, ]?(?<options>.*)/
|
224
|
-
|
225
|
-
ruby_code.scan(regex) do
|
226
|
-
m = $LAST_MATCH_INFO
|
227
|
-
|
228
|
-
# spaces = m[:spaces] # .delete("\n")
|
229
|
-
# last_lf = spaces.rindex("\n")
|
230
|
-
# spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
|
231
|
-
name = m[:name]
|
232
|
-
options = m[:options]
|
233
|
-
.gsub(':dependent => ', 'dependent: ')
|
234
|
-
.gsub(':class_name => ', 'class_name: ')
|
235
|
-
.gsub(':foreign_key => ', 'foreign_key: ')
|
236
|
-
.gsub(':primary_key => ', 'primary_key: ')
|
237
|
-
.strip
|
238
|
-
|
239
|
-
options = clean_lambda(options)
|
240
|
-
|
241
|
-
entries << { name: name, options: extract_options(options), raw_options: options }
|
242
|
-
end
|
243
|
-
entries
|
244
|
-
rescue StandardError => e
|
245
|
-
# bin ding.pry
|
246
|
-
puts e.message
|
247
|
-
end
|
248
|
-
|
249
|
-
def grab_has_and_belongs_to_many
|
250
|
-
entries = []
|
251
|
-
# Start from beginning of line and capture
|
252
|
-
# - number of spaces before has_and_belongs_to_many
|
253
|
-
# - name of the has_and_belongs_to_many
|
254
|
-
# - value of has_and_belongs_to_many to end of line
|
255
|
-
regex = /^(?<spaces>\s*)has_and_belongs_to_many :(?<name>\w*)[, ]?(?<options>.*)/
|
256
|
-
|
257
|
-
ruby_code.scan(regex) do
|
258
|
-
m = $LAST_MATCH_INFO
|
259
|
-
|
260
|
-
# spaces = m[:spaces] # .delete("\n")
|
261
|
-
# last_lf = spaces.rindex("\n")
|
262
|
-
# spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
|
263
|
-
name = m[:name]
|
264
|
-
options = m[:options]
|
265
|
-
.gsub(':dependent => ', 'dependent: ')
|
266
|
-
.gsub(':class_name => ', 'class_name: ')
|
267
|
-
.gsub(':foreign_key => ', 'foreign_key: ')
|
268
|
-
.gsub(':primary_key => ', 'primary_key: ')
|
269
|
-
.strip
|
270
|
-
|
271
|
-
options = clean_lambda(options)
|
272
|
-
|
273
|
-
entries << { name: name, options: {}, raw_options: options }
|
274
|
-
end
|
275
|
-
entries
|
276
|
-
rescue StandardError => e
|
277
|
-
# bin ding.pry
|
278
|
-
puts e.message
|
279
|
-
end
|
280
|
-
|
281
|
-
def grab_validates
|
282
|
-
entries = []
|
283
|
-
# Start from beginning of line and capture
|
284
|
-
# - number of spaces before validates
|
285
|
-
# - name of the validates
|
286
|
-
# - value of validates to end of line
|
287
|
-
regex = /^(?<spaces>\s*)validates :(?<name>\w*)[, ]?(?<options>.*)/
|
288
|
-
|
289
|
-
ruby_code.scan(regex) do
|
290
|
-
m = $LAST_MATCH_INFO
|
291
|
-
|
292
|
-
# spaces = m[:spaces] # .delete("\n")
|
293
|
-
# last_lf = spaces.rindex("\n")
|
294
|
-
# spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
|
295
|
-
name = m[:name]
|
296
|
-
|
297
|
-
options = m[:options].strip
|
298
|
-
|
299
|
-
options = clean_lambda(options)
|
300
|
-
|
301
|
-
entries << { name: name, raw_options: options }
|
302
|
-
end
|
303
|
-
entries
|
304
|
-
rescue StandardError => e
|
305
|
-
# bin ding.pry
|
306
|
-
puts e.message
|
307
|
-
end
|
308
|
-
|
309
|
-
def grab_validate
|
310
|
-
entries = []
|
311
|
-
# Start from beginning of line and capture
|
312
|
-
# - number of spaces before validate
|
313
|
-
# - list of methods to call until to end of line
|
314
|
-
# regex = /^(?<spaces>\s*)validate :(?<name>\w*)[, ]?(?<options>.*)/
|
315
|
-
regex = /^(?<spaces>\s*)validate (?<line>:.*)/
|
316
|
-
# puts @current_entity[:name]
|
317
|
-
|
318
|
-
ruby_code.scan(regex) do
|
319
|
-
m = $LAST_MATCH_INFO
|
320
|
-
|
321
|
-
# spaces = m[:spaces] # .delete("\n")
|
322
|
-
# last_lf = spaces.rindex("\n")
|
323
|
-
# spaces = last_lf ? spaces[spaces.rindex("\n") + 1..-1] : spaces
|
324
|
-
line = m[:line]
|
325
|
-
|
326
|
-
entries << { line: line }
|
327
|
-
# puts @current_entity[:validate]
|
328
|
-
end
|
329
|
-
entries
|
330
|
-
rescue StandardError => e
|
331
|
-
# bin ding.pry
|
332
|
-
puts e.message
|
333
|
-
end
|
334
|
-
|
335
|
-
def grab_methods(public_code = ruby_code, private_code = nil)
|
336
|
-
# public_code = ruby_code_public.nil? ? ruby_code : ruby_code_public
|
337
|
-
# private_code = ruby_code_private
|
338
|
-
|
339
|
-
regex = /def (?<method>.*)/
|
340
|
-
|
341
|
-
# log.info(@current_entity[:name])
|
342
|
-
|
343
|
-
public_methods = parse_methods(:public, public_code&.scan(regex)&.flatten || [])
|
344
|
-
private_methods = parse_methods(:private, private_code&.scan(regex)&.flatten || [])
|
345
|
-
methods = (public_methods + private_methods)
|
346
|
-
|
347
|
-
class_methods = methods.select { |method| method[:class_method] == true }
|
348
|
-
|
349
|
-
all_instance = methods.select { |method| method[:class_method] == false }
|
350
|
-
instance_public = all_instance.select { |method| method[:scope] == :public }
|
351
|
-
instance_private = all_instance.select { |method| method[:scope] == :private }
|
352
|
-
|
353
|
-
{
|
354
|
-
klass: class_methods,
|
355
|
-
instance: all_instance,
|
356
|
-
instance_public: instance_public,
|
357
|
-
instance_private: instance_private
|
358
|
-
}
|
359
|
-
end
|
360
|
-
|
361
|
-
def parse_methods(scope, methods)
|
362
|
-
methods.map do |value|
|
363
|
-
class_method = value.starts_with?('self.')
|
364
|
-
name = class_method ? value[5..-1] : value
|
365
|
-
arguments = nil
|
366
|
-
arguments_index = name.index('(')
|
367
|
-
|
368
|
-
if arguments_index
|
369
|
-
arguments = name[arguments_index..-1]
|
370
|
-
name = name[0..arguments_index - 1]
|
371
|
-
end
|
372
|
-
|
373
|
-
arguments = escape_single_quote(arguments)
|
374
|
-
|
375
|
-
{
|
376
|
-
name: name,
|
377
|
-
scope: scope,
|
378
|
-
class_method: class_method,
|
379
|
-
arguments: arguments&.strip.to_s
|
380
|
-
}
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
def todo
|
385
|
-
{
|
386
|
-
after_destroy: [], # to do
|
387
|
-
before_save: [], # to do
|
388
|
-
after_save: [], # to do
|
389
|
-
before_create: [], # to do
|
390
|
-
after_create: [], # to do
|
391
|
-
enum: [], # to do
|
392
|
-
attr_encrypted: [], # to do
|
393
|
-
validates_uniqueness_of: [], # to do
|
394
|
-
validates_confirmation_of: [], # to do
|
395
|
-
attr_accessor: [], # to do
|
396
|
-
attr_reader: [], # to do
|
397
|
-
attr_writer: [] # to do
|
398
|
-
}
|
399
|
-
end
|
400
|
-
|
401
|
-
def escape_single_quote(value)
|
402
|
-
return nil if value.nil?
|
403
|
-
|
404
|
-
value.gsub("'", "\\\\'")
|
405
|
-
end
|
406
|
-
|
407
|
-
# rubocop:disable Style/EvalWithLocation, Security/Eval, Style/DocumentDynamicEvalDefinition
|
408
|
-
def extract_options(options)
|
409
|
-
eval("{ #{options} }")
|
410
|
-
rescue StandardError => e
|
411
|
-
investigate(
|
412
|
-
step: :step4_attach_erd_files_models,
|
413
|
-
location: :extract_options,
|
414
|
-
key: nil,
|
415
|
-
message: e.message
|
416
|
-
)
|
417
|
-
{}
|
418
|
-
rescue SyntaxError => e
|
419
|
-
# may be the issue is from a comment at the off the line
|
420
|
-
comment_index = options.rindex('#') - 1
|
421
|
-
|
422
|
-
if comment_index.positive?
|
423
|
-
options_minus_comment = options[0..comment_index].squish
|
424
|
-
return extract_options(options_minus_comment)
|
425
|
-
end
|
426
|
-
|
427
|
-
investigate(
|
428
|
-
step: :step4_attach_erd_files_models,
|
429
|
-
location: :extract_options,
|
430
|
-
key: nil,
|
431
|
-
message: e.message
|
432
|
-
)
|
433
|
-
{}
|
434
|
-
end
|
435
|
-
# rubocop:enable Style/EvalWithLocation, Security/Eval, Style/DocumentDynamicEvalDefinition
|
436
|
-
|
437
|
-
def clean_lambda(options)
|
438
|
-
if /^->/.match?(options)
|
439
|
-
index = options.index(/}\s*,/)
|
440
|
-
if index.nil?
|
441
|
-
if options.count('{') == options.count('}')
|
442
|
-
index = options.rindex(/}/)
|
443
|
-
options = "a_lambda: '#{escape_single_quote(options[0..index])}'"
|
444
|
-
else
|
445
|
-
log.error(options)
|
446
|
-
options = "a_lambda: '#{escape_single_quote(options)}'"
|
447
|
-
end
|
448
|
-
else
|
449
|
-
options = "a_lambda: '#{escape_single_quote(options[0..index])}', #{options[index + 2..-1]}"
|
450
|
-
end
|
451
|
-
end
|
452
|
-
options
|
453
|
-
rescue StandardError => e
|
454
|
-
# bin ding.pry
|
455
|
-
puts e.message
|
456
|
-
end
|
457
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Locate rails model files
|
4
|
-
class Step9RailsStructureModels < 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_structure_models = rails_resource_models.map do |resource|
|
11
|
-
process_resource(OpenStruct.new(resource))
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def process_resource(resource)
|
18
|
-
erd_path = opts[:erd_path]
|
19
|
-
puts erd_path
|
20
|
-
@model = {
|
21
|
-
model_name: resource.model_name,
|
22
|
-
table_name: resource.table_name,
|
23
|
-
file: resource.file,
|
24
|
-
exist: resource.exist,
|
25
|
-
state: resource.state,
|
26
|
-
code: resource.exist ? File.read(resource.file) : '',
|
27
|
-
behaviours: {},
|
28
|
-
functions: {}
|
29
|
-
}
|
30
|
-
|
31
|
-
@model
|
32
|
-
end
|
33
|
-
end
|