k_domain 0.0.16 → 0.0.26
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/.builders/boot.rb +40 -0
- data/.builders/generators/configuration_generator.rb +22 -0
- data/.builders/run.rb +16 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -2
- data/Guardfile +1 -0
- data/README.md +15 -0
- data/STORIES.md +35 -6
- data/lib/k_domain/config/_.rb +4 -0
- data/lib/k_domain/config/config.rb +19 -0
- data/lib/k_domain/config/configuration.rb +76 -0
- data/lib/k_domain/domain_model/load.rb +41 -0
- data/lib/k_domain/domain_model/transform.rb +27 -55
- data/lib/k_domain/domain_model/transform_steps/_.rb +8 -7
- data/lib/k_domain/domain_model/transform_steps/step.rb +27 -1
- data/lib/k_domain/domain_model/transform_steps/{step1_attach_db_schema.rb → step1_db_schema.rb} +2 -1
- data/lib/k_domain/domain_model/transform_steps/{step5_attach_dictionary.rb → step20_dictionary.rb} +7 -4
- data/lib/k_domain/domain_model/transform_steps/step2_domain_models.rb +123 -0
- data/lib/k_domain/domain_model/transform_steps/{step8_rails_resource_models.rb → step4_rails_resource_models.rb} +4 -4
- data/lib/k_domain/domain_model/transform_steps/step5_rails_resource_routes.rb +36 -0
- data/lib/k_domain/domain_model/transform_steps/step6_rails_structure_models.rb +90 -0
- data/lib/k_domain/domain_model/transform_steps/step7_rails_structure_controllers.rb +111 -0
- data/lib/k_domain/domain_model/transform_steps/step8_domain_columns.rb +99 -0
- data/lib/k_domain/rails_code_extractor/_.rb +5 -0
- data/lib/k_domain/rails_code_extractor/extract_controller.rb +61 -0
- data/lib/k_domain/rails_code_extractor/extract_model.rb +56 -6
- data/lib/k_domain/rails_code_extractor/{load_shim.rb → shim_loader.rb} +3 -5
- data/lib/k_domain/raw_db_schema/load.rb +1 -1
- data/lib/k_domain/raw_db_schema/transform.rb +28 -3
- data/lib/k_domain/schemas/_.rb +6 -3
- data/lib/k_domain/schemas/database.rb +86 -0
- data/lib/k_domain/schemas/domain/erd_file.rb +78 -77
- data/lib/k_domain/schemas/domain.rb +149 -0
- data/lib/k_domain/schemas/domain_model.rb +6 -5
- data/lib/k_domain/schemas/{domain/_.rb → domain_types.rb} +1 -8
- data/lib/k_domain/schemas/rails_resource.rb +43 -6
- data/lib/k_domain/schemas/rails_structure.rb +182 -0
- data/lib/k_domain/version.rb +1 -1
- data/lib/k_domain.rb +4 -2
- data/templates/custom/action_controller.rb +36 -0
- data/templates/custom/controller_interceptors.rb +78 -0
- data/templates/custom/model_interceptors.rb +71 -0
- data/templates/load_schema.rb +7 -0
- data/templates/rails/action_controller.rb +301 -0
- data/templates/{active_record_shims.rb → rails/active_record.rb} +42 -49
- data/templates/ruby_code_extractor/attach_class_info.rb +13 -0
- data/templates/ruby_code_extractor/behaviour_accessors.rb +39 -0
- data/templates/sample_config.rb +47 -0
- data/templates/simple/controller_interceptors.rb +2 -0
- metadata +33 -22
- data/lib/k_domain/domain_model/transform_steps/step2_attach_models.rb +0 -62
- data/lib/k_domain/domain_model/transform_steps/step3_attach_columns.rb +0 -137
- 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
- data/lib/k_domain/schemas/database/_.rb +0 -7
- data/lib/k_domain/schemas/database/foreign_key.rb +0 -14
- data/lib/k_domain/schemas/database/index.rb +0 -14
- data/lib/k_domain/schemas/database/schema.rb +0 -31
- data/lib/k_domain/schemas/database/table.rb +0 -32
- data/lib/k_domain/schemas/domain/domain.rb +0 -11
- data/lib/k_domain/schemas/domain/models/column.rb +0 -49
- data/lib/k_domain/schemas/domain/models/model.rb +0 -111
- data/templates/fake_module_shims.rb +0 -42
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Schema is re-shaped into a format designed for domain modeling
|
4
|
+
class Step2DomainModels < KDomain::DomainModel::Step
|
5
|
+
# Map database schema to domain model
|
6
|
+
def call
|
7
|
+
raise 'Rails model path not supplied' if opts[:model_path].nil?
|
8
|
+
|
9
|
+
domain[:models] = database_tables.map { |table| model(table) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def model(table)
|
13
|
+
table_name = table[:name].to_s
|
14
|
+
model_name = table_name.singularize
|
15
|
+
|
16
|
+
model = {
|
17
|
+
name: model_name,
|
18
|
+
name_plural: table_name, # need to check if this is correct as I know it is wrong for account_history_datum
|
19
|
+
table_name: table_name,
|
20
|
+
pk: primary_key(table),
|
21
|
+
file: nil # will be set in step8_domain_columns
|
22
|
+
}
|
23
|
+
|
24
|
+
attach_columns(model)
|
25
|
+
end
|
26
|
+
|
27
|
+
def primary_key(table)
|
28
|
+
{
|
29
|
+
name: table[:primary_key],
|
30
|
+
type: table[:primary_key_type],
|
31
|
+
exist: !table[:primary_key].nil?
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def attach_columns(model)
|
36
|
+
table = find_table_for_model(model)
|
37
|
+
columns = columns(table[:columns])
|
38
|
+
columns = insert_primary_key(model, columns)
|
39
|
+
model[:columns] = columns
|
40
|
+
model
|
41
|
+
end
|
42
|
+
|
43
|
+
def columns(db_columns)
|
44
|
+
db_columns.map do |db_column|
|
45
|
+
column_data(db_column[:name]).merge(
|
46
|
+
type: check_type(db_column[:type]),
|
47
|
+
precision: db_column[:precision],
|
48
|
+
scale: db_column[:scale],
|
49
|
+
default: db_column[:default],
|
50
|
+
null: db_column[:null],
|
51
|
+
limit: db_column[:limit],
|
52
|
+
array: db_column[:array]
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def insert_primary_key(model, columns)
|
58
|
+
return columns unless model[:pk][:exist]
|
59
|
+
|
60
|
+
column = column_data('id').merge(
|
61
|
+
type: check_type(model[:pk][:type])
|
62
|
+
)
|
63
|
+
|
64
|
+
columns.unshift(column)
|
65
|
+
columns
|
66
|
+
end
|
67
|
+
|
68
|
+
def check_type(type)
|
69
|
+
type = type.to_sym if type.is_a?(String)
|
70
|
+
|
71
|
+
return type if %i[string integer bigint bigserial boolean float decimal datetime date hstore text jsonb].include?(type)
|
72
|
+
|
73
|
+
if type.nil?
|
74
|
+
guard('nil type detected for db_column[:type]')
|
75
|
+
|
76
|
+
return :string
|
77
|
+
end
|
78
|
+
|
79
|
+
guard("new type detected for db_column[:type] - #{type}")
|
80
|
+
|
81
|
+
camel.parse(type.to_s).downcase
|
82
|
+
end
|
83
|
+
|
84
|
+
def column_data(name)
|
85
|
+
{
|
86
|
+
name: name,
|
87
|
+
name_plural: name.pluralize,
|
88
|
+
type: nil,
|
89
|
+
precision: nil,
|
90
|
+
scale: nil,
|
91
|
+
default: nil,
|
92
|
+
null: nil,
|
93
|
+
limit: nil,
|
94
|
+
array: nil
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
# # Location of source code
|
99
|
+
# def location(table_name, model_name)
|
100
|
+
# file_normal = File.join(opts[:model_path], "#{model_name}.rb")
|
101
|
+
# file_custom = File.join(opts[:model_path], "#{table_name}.rb")
|
102
|
+
# file_exist = true
|
103
|
+
# state = []
|
104
|
+
|
105
|
+
# if File.exist?(file_normal)
|
106
|
+
# file = file_normal
|
107
|
+
# state.push(:has_ruby_model)
|
108
|
+
# elsif File.exist?(file_custom)
|
109
|
+
# file = file_custom
|
110
|
+
# state.push(:has_ruby_model)
|
111
|
+
# state.push(:nonconventional_name)
|
112
|
+
# else
|
113
|
+
# file = ''
|
114
|
+
# file_exist = false
|
115
|
+
# end
|
116
|
+
|
117
|
+
# {
|
118
|
+
# file: file,
|
119
|
+
# exist: file_exist,
|
120
|
+
# state: state
|
121
|
+
# }
|
122
|
+
# end
|
123
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Locate rails model files
|
4
|
-
class
|
4
|
+
class Step4RailsResourceModels < KDomain::DomainModel::Step
|
5
5
|
attr_accessor :ruby_code
|
6
6
|
|
7
7
|
def call
|
8
|
-
raise '
|
8
|
+
raise 'Model path not supplied' if opts[:model_path].nil?
|
9
9
|
|
10
10
|
self.rails_resource_models = domain_models.map do |model|
|
11
11
|
locate_rails_model(model[:name], model[:table_name])
|
@@ -15,8 +15,8 @@ class Step8RailsResourceModels < KDomain::DomainModel::Step
|
|
15
15
|
private
|
16
16
|
|
17
17
|
def locate_rails_model(model_name, table_name)
|
18
|
-
file_normal = File.join(opts[:
|
19
|
-
file_custom = File.join(opts[:
|
18
|
+
file_normal = File.join(opts[:model_path], "#{model_name}.rb")
|
19
|
+
file_custom = File.join(opts[:model_path], "#{table_name}.rb")
|
20
20
|
file_exist = true
|
21
21
|
state = []
|
22
22
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Locate rails model files
|
4
|
+
class Step5RailsResourceRoutes < KDomain::DomainModel::Step
|
5
|
+
def call
|
6
|
+
return warning('Routes .json file not supplied') if opts[:route_path].nil?
|
7
|
+
return warning('Routes .json file not found') unless File.exist?(opts[:route_path])
|
8
|
+
|
9
|
+
warning('Controller path not supplied. Routes will be loaded but not paired with a controller') if opts[:controller_path].nil?
|
10
|
+
|
11
|
+
self.rails_resource_routes = load_routes(opts[:route_path], opts[:controller_path])
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def load_routes(route_path, controller_path)
|
17
|
+
json = File.read(route_path)
|
18
|
+
root = JSON.parse(json, symbolize_names: true)
|
19
|
+
routes = root[:routes]
|
20
|
+
|
21
|
+
routes.map { |route| map_route(route, controller_path) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def map_route(route, controller_path)
|
25
|
+
return route.merge({ file: '', exist: false }) if controller_path.nil?
|
26
|
+
|
27
|
+
controller_file = File.join(controller_path, route[:controller_file])
|
28
|
+
|
29
|
+
route.merge(
|
30
|
+
{
|
31
|
+
file: controller_file,
|
32
|
+
exist: File.exist?(controller_file)
|
33
|
+
}
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Locate rails model files
|
4
|
+
class Step6RailsStructureModels < KDomain::DomainModel::Step
|
5
|
+
def call
|
6
|
+
raise 'Rails model path not supplied' unless opts[:model_path]
|
7
|
+
|
8
|
+
# THIS IS NOT WORKING YET
|
9
|
+
self.rails_structure_models = rails_resource_models.map do |resource|
|
10
|
+
process_resource(OpenStruct.new(resource))
|
11
|
+
end
|
12
|
+
|
13
|
+
attach_behavior_and_functions
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def process_resource(resource)
|
19
|
+
{
|
20
|
+
model_name: resource.model_name,
|
21
|
+
table_name: resource.table_name,
|
22
|
+
file: resource.file,
|
23
|
+
exist: resource.exist,
|
24
|
+
state: resource.state,
|
25
|
+
code: resource.exist ? File.read(resource.file) : '',
|
26
|
+
behaviours: {},
|
27
|
+
functions: {}
|
28
|
+
}
|
29
|
+
|
30
|
+
# return @model unless resource.exist
|
31
|
+
|
32
|
+
# @model[:behaviours] = extract_behavior(resource.file)
|
33
|
+
# @model[:functions] = extract_functions(resource.file)
|
34
|
+
|
35
|
+
# @model
|
36
|
+
end
|
37
|
+
|
38
|
+
def attach_behavior_and_functions
|
39
|
+
rails_structure_models.select { |model| model[:exist] }.each do |model|
|
40
|
+
model[:behaviours] = extract_behavior(model[:file])
|
41
|
+
klass_name = model[:behaviours][:class_name]
|
42
|
+
model[:functions] = extract_functions(klass_name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def extract_behavior(file)
|
47
|
+
extractor.extract(file)
|
48
|
+
extractor.model
|
49
|
+
end
|
50
|
+
|
51
|
+
def extract_functions(klass_name)
|
52
|
+
klass = klass_type(klass_name)
|
53
|
+
|
54
|
+
return {} if klass.nil?
|
55
|
+
|
56
|
+
Peeky.api.build_class_info(klass.new).to_h
|
57
|
+
rescue StandardError => e
|
58
|
+
log.exception(e)
|
59
|
+
end
|
60
|
+
|
61
|
+
def klass_type(klass_name)
|
62
|
+
Module.const_get(klass_name.classify)
|
63
|
+
rescue NameError
|
64
|
+
puts ''
|
65
|
+
puts klass_name
|
66
|
+
puts klass_name.classify
|
67
|
+
puts klass_name.pluralize
|
68
|
+
puts 'Trying the pluralized version: '
|
69
|
+
Module.const_get(klass_name.pluralize)
|
70
|
+
end
|
71
|
+
|
72
|
+
def extractor
|
73
|
+
@extractor ||= KDomain::RailsCodeExtractor::ExtractModel.new(shim_loader)
|
74
|
+
end
|
75
|
+
|
76
|
+
def shim_loader
|
77
|
+
return opts[:shim_loader] if !opts[:shim_loader].nil? && opts[:shim_loader].is_a?(KDomain::RailsCodeExtractor::ShimLoader)
|
78
|
+
|
79
|
+
shim_loader = KDomain::RailsCodeExtractor::ShimLoader.new
|
80
|
+
# Shims to attach generic class_info writers
|
81
|
+
shim_loader.register(:attach_class_info , KDomain::Gem.resource('templates/ruby_code_extractor/attach_class_info.rb'))
|
82
|
+
shim_loader.register(:behaviour_accessors , KDomain::Gem.resource('templates/ruby_code_extractor/behaviour_accessors.rb'))
|
83
|
+
|
84
|
+
# Shims to support standard active_record DSL methods
|
85
|
+
shim_loader.register(:active_record , KDomain::Gem.resource('templates/rails/active_record.rb'))
|
86
|
+
|
87
|
+
# Shims to support application specific [module, class, method] implementations for suppression and exception avoidance
|
88
|
+
shim_loader
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Locate rails controller files
|
4
|
+
class Step7RailsStructureControllers < KDomain::DomainModel::Step
|
5
|
+
attr_accessor :controllers
|
6
|
+
|
7
|
+
def call
|
8
|
+
raise 'Rails controller path not supplied' unless opts[:controller_path]
|
9
|
+
|
10
|
+
@controllers = {}
|
11
|
+
|
12
|
+
rails_resource_routes.map do |route|
|
13
|
+
process_route(OpenStruct.new(route))
|
14
|
+
end
|
15
|
+
|
16
|
+
self.rails_structure_controllers = controllers.keys.map { |key| controllers[key] }
|
17
|
+
|
18
|
+
attach_behavior_and_functions
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def process_route(route)
|
24
|
+
if new_controller?(route)
|
25
|
+
new_controller(route)
|
26
|
+
else
|
27
|
+
controller = @controllers[route[:controller_file]]
|
28
|
+
controller[:actions] << new_action(route)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_controller?(route)
|
33
|
+
!controllers.key?(route[:controller_file])
|
34
|
+
end
|
35
|
+
|
36
|
+
def new_controller(route)
|
37
|
+
controllers[route[:controller_file]] = {
|
38
|
+
name: route[:controller_name],
|
39
|
+
path: route[:controller_path],
|
40
|
+
namespace: route[:controller_namespace],
|
41
|
+
file: route[:controller_file],
|
42
|
+
exist: route[:controller_exist],
|
43
|
+
full_file: route[:file],
|
44
|
+
behaviours: {},
|
45
|
+
functions: {},
|
46
|
+
actions: [new_action(route)]
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def new_action(route)
|
51
|
+
{
|
52
|
+
route_name: route[:name],
|
53
|
+
action: route[:action],
|
54
|
+
uri_path: route[:uri_path],
|
55
|
+
mime_match: route[:mime_match],
|
56
|
+
verbs: route[:verbs]
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def attach_behavior_and_functions
|
61
|
+
rails_structure_controllers.select { |controller| controller[:exist] }.each do |controller|
|
62
|
+
unless File.exist?(controller[:full_file])
|
63
|
+
log.error 'Controller apparently exists but no file found, this means that you need re-run rake routes'
|
64
|
+
puts controller[:full_file]
|
65
|
+
next
|
66
|
+
end
|
67
|
+
controller[:behaviours] = extract_behavior(controller[:full_file])
|
68
|
+
klass_name = controller[:behaviours][:class_name]
|
69
|
+
controller[:functions] = extract_functions(klass_name, controller[:full_file])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def extract_behavior(file)
|
74
|
+
# puts file
|
75
|
+
extractor.extract(file)
|
76
|
+
extractor.controller
|
77
|
+
end
|
78
|
+
|
79
|
+
def extractor
|
80
|
+
@extractor ||= KDomain::RailsCodeExtractor::ExtractController.new(shim_loader)
|
81
|
+
end
|
82
|
+
|
83
|
+
def shim_loader
|
84
|
+
return opts[:shim_loader] if !opts[:shim_loader].nil? && opts[:shim_loader].is_a?(KDomain::RailsCodeExtractor::ShimLoader)
|
85
|
+
|
86
|
+
shim_loader = KDomain::RailsCodeExtractor::ShimLoader.new
|
87
|
+
# Shims to attach generic class_info writers
|
88
|
+
shim_loader.register(:attach_class_info , KDomain::Gem.resource('templates/ruby_code_extractor/attach_class_info.rb'))
|
89
|
+
shim_loader.register(:behaviour_accessors , KDomain::Gem.resource('templates/ruby_code_extractor/behaviour_accessors.rb'))
|
90
|
+
|
91
|
+
# Shims to support stand rails controller DSL methods
|
92
|
+
shim_loader.register(:action_controller , KDomain::Gem.resource('templates/rails/action_controller.rb'))
|
93
|
+
|
94
|
+
# Shims to support application specific [module, class, method] implementations for suppression and exception avoidance
|
95
|
+
# shim_loader.register(:app_action_controller , KDomain::Gem.resource('templates/advanced/action_controller.rb'))
|
96
|
+
# shim_loader.register(:app_controller_interceptors , KDomain::Gem.resource('templates/advanced/controller_interceptors.rb'))
|
97
|
+
shim_loader
|
98
|
+
end
|
99
|
+
|
100
|
+
def extract_functions(klass_name, controller_file)
|
101
|
+
klass = Module.const_get(klass_name.classify)
|
102
|
+
|
103
|
+
class_info = Peeky.api.build_class_info(klass.new)
|
104
|
+
|
105
|
+
class_info.to_h
|
106
|
+
rescue StandardError => e
|
107
|
+
log.kv 'controller_file', controller_file
|
108
|
+
log.exception(e, style: :short)
|
109
|
+
{}
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# columns to models
|
4
|
+
class Step8DomainColumns < KDomain::DomainModel::Step
|
5
|
+
attr_reader :domain_model
|
6
|
+
attr_reader :domain_column
|
7
|
+
attr_reader :rails_model
|
8
|
+
attr_reader :column_name
|
9
|
+
attr_reader :column_symbol
|
10
|
+
|
11
|
+
def call
|
12
|
+
@debug = true
|
13
|
+
enrich_columns
|
14
|
+
end
|
15
|
+
|
16
|
+
def enrich_columns
|
17
|
+
# .select {|m| m[:name] == 'app_user'}
|
18
|
+
domain_models.each do |model|
|
19
|
+
@domain_model = enrich_model(model)
|
20
|
+
# this will be nil if there is no rails model code
|
21
|
+
|
22
|
+
# log.warn domain_model[:name]
|
23
|
+
domain_model[:columns].each do |column|
|
24
|
+
@domain_column = column
|
25
|
+
@column_name = column[:name]
|
26
|
+
@column_symbol = column[:name].to_sym
|
27
|
+
|
28
|
+
column[:structure_type] = structure_type
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def enrich_model(model)
|
34
|
+
# NOTE: THIS MAY GET MOVED TO DomainModel::Load#enrichment
|
35
|
+
@rails_model = find_rails_structure_models(model[:name])
|
36
|
+
|
37
|
+
model[:file] = @rails_model[:file]
|
38
|
+
|
39
|
+
log.error "Rails model not found for: #{model[:name]}" unless @rails_model
|
40
|
+
|
41
|
+
model
|
42
|
+
end
|
43
|
+
|
44
|
+
# Need some configurable data dictionary where by
|
45
|
+
# _token can be setup on a project by project basis
|
46
|
+
def structure_type
|
47
|
+
return :primary_key if domain_model[:pk][:name] == column_name
|
48
|
+
return :foreign_key if foreign_relationship?
|
49
|
+
return :foreign_type if column_symbol == :context_type || column_symbol == :element_type
|
50
|
+
|
51
|
+
return :timestamp if column_symbol == :created_at || column_symbol == :updated_at
|
52
|
+
return :deleted_at if column_symbol == :deleted_at
|
53
|
+
return :encrypted_password if column_symbol == :encrypted_password
|
54
|
+
return :token if column_name.ends_with?('_token') || column_name.ends_with?('_token_iv')
|
55
|
+
|
56
|
+
:data
|
57
|
+
end
|
58
|
+
|
59
|
+
def foreign_relationship?
|
60
|
+
return false if rails_model.nil? || rails_model[:behaviours].nil? || rails_model[:behaviours][:belongs_to].nil?
|
61
|
+
|
62
|
+
column_name = domain_column[:name].to_sym
|
63
|
+
rails_model[:behaviours][:belongs_to].any? { |belong| belong[:opts][:foreign_key].to_sym == column_name }
|
64
|
+
end
|
65
|
+
|
66
|
+
# def attach_relationships
|
67
|
+
# domain_column[:relationships] = []
|
68
|
+
# return if rails_model.nil? || rails_model[:behaviours].nil? || rails_model[:behaviours][:belongs_to].nil?
|
69
|
+
|
70
|
+
# column_name = domain_column[:name].to_sym
|
71
|
+
|
72
|
+
# attach_column_relationships(column_name)
|
73
|
+
# end
|
74
|
+
|
75
|
+
# def select_belongs_to(column_name)
|
76
|
+
# rails_model[:behaviours][:belongs_to].select { |belong| belong[:opts][:foreign_key].to_sym == column_name.to_sym }
|
77
|
+
# end
|
78
|
+
|
79
|
+
# # this just maps basic relationship information,
|
80
|
+
# # to go deeper you really need to use the Rails Model Behaviours
|
81
|
+
# def attach_column_relationships(column_name)
|
82
|
+
# select_belongs_to(column_name).each do |belongs_to|
|
83
|
+
# domain_column[:relationships] << map_belongs_to(belongs_to)
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
|
87
|
+
# def map_belongs_to(belongs_to)
|
88
|
+
# @domain_column[:structure_type] = :foreign_key
|
89
|
+
# # result = {
|
90
|
+
# # type: :belongs_to,
|
91
|
+
# # name: belongs_to[:name],
|
92
|
+
# # foreign_key: belongs_to.dig(:opts, :foreign_key) || @domain_column[:name],
|
93
|
+
# # }
|
94
|
+
|
95
|
+
# # result[:primary_key] = belongs_to.dig(:opts, :primary_key) if belongs_to.dig(:opts, :primary_key)
|
96
|
+
# # result[:class_name] = belongs_to.dig(:opts, :class_name) if belongs_to.dig(:opts, :class_name)
|
97
|
+
# result
|
98
|
+
# end
|
99
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Takes a Rails controller and extracts DSL behaviours and custom functions (instance, class and private methods)
|
4
|
+
module KDomain
|
5
|
+
module RailsCodeExtractor
|
6
|
+
class ExtractController
|
7
|
+
include KLog::Logging
|
8
|
+
|
9
|
+
attr_reader :shims_loaded
|
10
|
+
attr_reader :controller
|
11
|
+
|
12
|
+
def initialize(load_shim)
|
13
|
+
@load_shim = load_shim
|
14
|
+
@shims_loaded = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def extract(file)
|
18
|
+
load_shims unless shims_loaded
|
19
|
+
|
20
|
+
ActionController.class_info = nil
|
21
|
+
# KDomain::RailsCodeExtractor.reset
|
22
|
+
|
23
|
+
load_retry(file, 10, nil)
|
24
|
+
rescue StandardError => e
|
25
|
+
log.exception(e)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def load_shims
|
31
|
+
@load_shim.call
|
32
|
+
@shims_loaded = true
|
33
|
+
end
|
34
|
+
|
35
|
+
# rubocop:disable Security/Eval,Style/EvalWithLocation,Style/DocumentDynamicEvalDefinition,Metrics/AbcSize
|
36
|
+
def load_retry(file, times, last_error)
|
37
|
+
return if times.negative?
|
38
|
+
|
39
|
+
# puts file
|
40
|
+
load(file)
|
41
|
+
|
42
|
+
@controller = ActionController::Base.class_info
|
43
|
+
# @controller = KDomain::RailsCodeExtractor.class_info
|
44
|
+
|
45
|
+
# get_method_info(File.base_name(file))
|
46
|
+
rescue StandardError => e
|
47
|
+
log.kv 'times', times
|
48
|
+
# puts e.message
|
49
|
+
if e.is_a?(NameError) && e.message != last_error&.message
|
50
|
+
log.kv('add module', e.name)
|
51
|
+
log.kv 'file', file
|
52
|
+
eval("module #{e.name}; end")
|
53
|
+
return load_retry(file, times - 1, e)
|
54
|
+
end
|
55
|
+
log.kv 'file', file
|
56
|
+
log.exception(e, style: :short, method_info: method(__callee__))
|
57
|
+
end
|
58
|
+
# rubocop:enable Security/Eval,Style/EvalWithLocation,Style/DocumentDynamicEvalDefinition,Metrics/AbcSize
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -6,16 +6,66 @@ 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.class_info = nil
|
23
|
+
|
24
|
+
load_retry(file, 10, nil)
|
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, last_error)
|
38
|
+
return if times.negative?
|
39
|
+
|
40
|
+
load(file)
|
41
|
+
|
42
|
+
@model = ActiveRecord.class_info
|
43
|
+
|
44
|
+
if @model.nil?
|
45
|
+
# puts ''
|
46
|
+
# puts file
|
47
|
+
# puts 'class probably has no DSL methods'
|
48
|
+
@model = {
|
49
|
+
class_name: File.basename(file, File.extname(file)).classify
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
@models << @model
|
54
|
+
|
55
|
+
# get_method_info(File.base_name(file))
|
56
|
+
rescue StandardError => e
|
57
|
+
log.kv 'times', times
|
58
|
+
# puts e.message
|
59
|
+
if e.is_a?(NameError) && e.message != last_error&.message
|
60
|
+
log.kv('add module', e.name)
|
61
|
+
log.kv 'file', file
|
62
|
+
eval("module #{e.name}; end")
|
63
|
+
return load_retry(file, times - 1, e)
|
64
|
+
end
|
65
|
+
log.kv 'file', file
|
66
|
+
log.exception(e, style: :short, method_info: method(__callee__))
|
18
67
|
end
|
68
|
+
# rubocop:enable Security/Eval,Style/EvalWithLocation,Style/DocumentDynamicEvalDefinition,Metrics/AbcSize
|
19
69
|
end
|
20
70
|
end
|
21
71
|
end
|
@@ -8,20 +8,18 @@
|
|
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
|
+
# puts shim_files.map { |sf| sf[:file] }
|
22
|
+
shim_files.select { |sf| sf[:exist] }.each { |sf| require sf[:file] }
|
25
23
|
end
|
26
24
|
|
27
25
|
def register(name, file)
|