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