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