k_domain 0.0.1 → 0.0.14
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/.rubocop.yml +39 -1
- data/Gemfile +10 -0
- data/Guardfile +30 -0
- data/Rakefile +3 -4
- data/STORIES.md +63 -0
- data/USAGE.md +19 -0
- data/k_domain.gemspec +4 -0
- data/lib/k_domain/domain_model/load.rb +29 -0
- data/lib/k_domain/domain_model/transform.rb +110 -0
- data/lib/k_domain/domain_model/transform_steps/_.rb +10 -0
- data/lib/k_domain/domain_model/transform_steps/step.rb +142 -0
- data/lib/k_domain/domain_model/transform_steps/step1_attach_db_schema.rb +21 -0
- data/lib/k_domain/domain_model/transform_steps/step2_attach_models.rb +62 -0
- data/lib/k_domain/domain_model/transform_steps/step3_attach_columns.rb +137 -0
- data/lib/k_domain/domain_model/transform_steps/step4_attach_erd_files.rb +454 -0
- data/lib/k_domain/domain_model/transform_steps/step5_attach_dictionary.rb +58 -0
- data/lib/k_domain/domain_model/transform_steps/step8_locate_rails_models.rb +44 -0
- data/lib/k_domain/raw_db_schema/load.rb +29 -0
- data/lib/k_domain/raw_db_schema/transform.rb +82 -0
- data/lib/k_domain/schemas/_.rb +15 -0
- data/lib/k_domain/schemas/database/_.rb +7 -0
- data/lib/k_domain/schemas/database/foreign_key.rb +14 -0
- data/lib/k_domain/schemas/database/index.rb +14 -0
- data/lib/k_domain/schemas/database/schema.rb +31 -0
- data/lib/k_domain/schemas/database/table.rb +32 -0
- data/lib/k_domain/schemas/dictionary.rb +19 -0
- data/lib/k_domain/schemas/domain/_.rb +65 -0
- data/lib/k_domain/schemas/domain/domain.rb +11 -0
- data/lib/k_domain/schemas/domain/erd_file.rb +80 -0
- data/lib/k_domain/schemas/domain/models/column.rb +49 -0
- data/lib/k_domain/schemas/domain/models/model.rb +111 -0
- data/lib/k_domain/schemas/domain/old/belongs_to.rb +25 -0
- data/lib/k_domain/schemas/domain/old/column_old.rb +225 -0
- data/lib/k_domain/schemas/domain/old/domain_statistics.rb +29 -0
- data/lib/k_domain/schemas/domain/old/entity.rb +338 -0
- data/lib/k_domain/schemas/domain/old/entity_statistics.rb +22 -0
- data/lib/k_domain/schemas/domain/old/foreign_key.rb +17 -0
- data/lib/k_domain/schemas/domain/old/has_and_belongs_to_many.rb +20 -0
- data/lib/k_domain/schemas/domain/old/has_many.rb +27 -0
- data/lib/k_domain/schemas/domain/old/has_one.rb +41 -0
- data/lib/k_domain/schemas/domain/old/name_options.rb +10 -0
- data/lib/k_domain/schemas/domain/old/rails_controller.rb +10 -0
- data/lib/k_domain/schemas/domain/old/rails_model.rb +92 -0
- data/lib/k_domain/schemas/domain/old/related_entity.rb +36 -0
- data/lib/k_domain/schemas/domain/old/statistics.rb +21 -0
- data/lib/k_domain/schemas/domain/old/validate.rb +25 -0
- data/lib/k_domain/schemas/domain/old/validates.rb +50 -0
- data/lib/k_domain/schemas/domain_model.rb +14 -0
- data/lib/k_domain/schemas/investigate.rb +15 -0
- data/lib/k_domain/schemas/rails_resource.rb +16 -0
- data/lib/k_domain/version.rb +1 -1
- data/lib/k_domain.rb +22 -1
- data/templates/load_schema.rb +226 -0
- metadata +91 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c236bd2b714a21b40f5727765bc2b9c049f0c265e7c592e5864a6a6e34330b37
|
4
|
+
data.tar.gz: 8ecf79ec6e1805ad6660218ac6aa6931ef67a48b3ca56dd339c7a6a0f6c50886
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b3a6c9c9af39c37fdeba462a209a0bd395a72c1887505c0852f1f37a58406c929cc080c63bb9ed5b4de937be51d722e0511a6194d7de389840cb5ca831e7135
|
7
|
+
data.tar.gz: f71d09378bf35ec9146692bd137b02176095ba934fbba711c6204896541af27365aeeeb67997d89d43cea7498f2d7361322cba566dd0c31ed1674fb190656968
|
data/.rubocop.yml
CHANGED
@@ -6,12 +6,37 @@ AllCops:
|
|
6
6
|
NewCops: enable
|
7
7
|
Exclude:
|
8
8
|
- "_/**/*"
|
9
|
-
- "spec/
|
9
|
+
- "spec/sample_input/**/*"
|
10
|
+
- "spec/sample_output/**/*"
|
11
|
+
- "lib/k_domain/raw_db_schema/template.rb"
|
12
|
+
|
13
|
+
Metrics/PerceivedComplexity:
|
14
|
+
Exclude:
|
15
|
+
- "lib/k_domain/domain_model/transform_steps/*.rb"
|
16
|
+
- "lib/k_domain/domain_model/dtos/entity.rb"
|
17
|
+
- "lib/k_domain/domain_model/dtos/old/entity.rb"
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Exclude:
|
21
|
+
- "lib/k_domain/domain_model/transform_steps/*.rb"
|
22
|
+
- "lib/k_domain/domain_model/dtos/rails_model.rb"
|
23
|
+
- "lib/k_domain/domain_model/dtos/entity.rb"
|
24
|
+
- "lib/k_domain/domain_model/dtos/column_old.rb"
|
25
|
+
- "lib/k_domain/domain_model/dtos/old/column_old.rb"
|
26
|
+
- "lib/k_domain/domain_model/dtos/old/rails_model.rb"
|
27
|
+
- "lib/k_domain/domain_model/dtos/old/entity.rb"
|
28
|
+
|
29
|
+
Metrics/CyclomaticComplexity:
|
30
|
+
Exclude:
|
31
|
+
- "lib/k_domain/domain_model/transform_steps/*.rb"
|
32
|
+
- "lib/k_domain/domain_model/dtos/entity.rb"
|
33
|
+
- "lib/k_domain/domain_model/dtos/old/entity.rb"
|
10
34
|
|
11
35
|
Metrics/BlockLength:
|
12
36
|
Exclude:
|
13
37
|
- "**/spec/**/*"
|
14
38
|
- "*.gemspec"
|
39
|
+
- 'lib/k_domain/domain_model/dtos/erd_file.rb'
|
15
40
|
IgnoredMethods:
|
16
41
|
- configure
|
17
42
|
- context
|
@@ -34,12 +59,19 @@ Metrics/BlockLength:
|
|
34
59
|
|
35
60
|
Metrics/MethodLength:
|
36
61
|
Max: 25
|
62
|
+
Exclude:
|
63
|
+
- "lib/k_domain/domain_model/transform_steps/*.rb"
|
64
|
+
- "lib/k_domain/domain_model/dtos/rails_model.rb"
|
65
|
+
- "lib/k_domain/domain_model/dtos/old/entity.rb"
|
66
|
+
- "lib/k_domain/domain_model/dtos/old/rails_model.rb"
|
37
67
|
|
38
68
|
Layout/LineLength:
|
39
69
|
Max: 200
|
40
70
|
# Ignores annotate output
|
41
71
|
IgnoredPatterns: ['\A# \*\*']
|
42
72
|
IgnoreCopDirectives: true
|
73
|
+
Exclude:
|
74
|
+
- "lib/k_domain/domain_model/transform_steps/*.rb"
|
43
75
|
|
44
76
|
Lint/UnusedMethodArgument:
|
45
77
|
AllowUnusedKeywordArguments: true
|
@@ -77,6 +109,12 @@ Lint/AmbiguousBlockAssociation:
|
|
77
109
|
Style/AccessorGrouping:
|
78
110
|
Enabled: false
|
79
111
|
|
112
|
+
Style/FormatStringToken:
|
113
|
+
Enabled: false
|
114
|
+
|
115
|
+
Style/Documentation:
|
116
|
+
Enabled: false
|
117
|
+
|
80
118
|
Layout/SpaceBeforeComma:
|
81
119
|
Enabled: false
|
82
120
|
# My Preferences - End
|
data/Gemfile
CHANGED
@@ -23,3 +23,13 @@ group :development, :test do
|
|
23
23
|
gem 'rubocop-rake', require: false
|
24
24
|
gem 'rubocop-rspec', require: false
|
25
25
|
end
|
26
|
+
|
27
|
+
# If local dependency
|
28
|
+
if ENV['KLUE_LOCAL_GEMS']&.to_s&.downcase == 'true'
|
29
|
+
group :development, :test do
|
30
|
+
puts 'Using Local GEMs'
|
31
|
+
gem 'peeky' , path: '../peeky'
|
32
|
+
gem 'k_log' , path: '../k_log'
|
33
|
+
gem 'k_util' , path: '../k_util'
|
34
|
+
end
|
35
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
guard :bundler, cmd: 'bundle install' do
|
4
|
+
watch('Gemfile')
|
5
|
+
watch('k_domain.gemspec')
|
6
|
+
end
|
7
|
+
|
8
|
+
group :green_pass_then_cop, halt_on_fail: true do
|
9
|
+
guard :rspec, cmd: 'bundle exec rspec -f doc' do
|
10
|
+
require 'guard/rspec/dsl'
|
11
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
12
|
+
|
13
|
+
# RSpec files
|
14
|
+
rspec = dsl.rspec
|
15
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
16
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
17
|
+
watch(rspec.spec_files)
|
18
|
+
|
19
|
+
# Ruby files
|
20
|
+
ruby = dsl.ruby
|
21
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
22
|
+
watch(%r{^lib/k_domain/**/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
|
23
|
+
watch(%r{^lib/k_domain/commands/(.+)\.rb$}) { |m| "spec/unit/commands/#{m[1]}_spec.rb" }
|
24
|
+
end
|
25
|
+
|
26
|
+
# guard :rubocop, all_on_start: false, cli: ['--format', 'clang'] do
|
27
|
+
# watch(/{.+\.rb$/)
|
28
|
+
# watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
|
29
|
+
# end
|
30
|
+
end
|
data/Rakefile
CHANGED
@@ -7,11 +7,8 @@ GEM_NAME = 'k_domain'
|
|
7
7
|
require 'pry'
|
8
8
|
require 'bundler/gem_tasks'
|
9
9
|
require 'rspec/core/rake_task'
|
10
|
-
puts 'xxxxxxxxxx'
|
11
10
|
require 'k_domain'
|
12
11
|
require 'k_domain/version'
|
13
|
-
puts 'xxxxxxxxxx2'
|
14
|
-
binding.pry
|
15
12
|
|
16
13
|
RSpec::Core::RakeTask.new(:spec)
|
17
14
|
|
@@ -29,7 +26,9 @@ task :publish do
|
|
29
26
|
system 'gem build'
|
30
27
|
system "gem push #{GEM_NAME}-#{KDomain::VERSION}.gem"
|
31
28
|
end
|
32
|
-
|
29
|
+
task :build do
|
30
|
+
system 'gem build'
|
31
|
+
end
|
33
32
|
desc 'Remove old *.gem files'
|
34
33
|
task :clean do
|
35
34
|
system 'rm *.gem'
|
data/STORIES.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# K Domain
|
2
|
+
|
3
|
+
> K Domain builds complex domain schemas by combining the database schema with a rich entity relationship DSLs
|
4
|
+
|
5
|
+
As an Application Developer, I need a rich and configurable ERD schema, so I can generate enterprise applications quickly
|
6
|
+
|
7
|
+
## Development radar
|
8
|
+
|
9
|
+
### Stories next on list
|
10
|
+
|
11
|
+
As a Developer, I can print any of the domain structures, so that I can visually my domain
|
12
|
+
|
13
|
+
- Hook up log.structure
|
14
|
+
|
15
|
+
As a Developer, I can customize domain configuration, so that I can have opinions about names and types
|
16
|
+
|
17
|
+
- Handle traits
|
18
|
+
|
19
|
+
As a Developer, I can read native rails model data, so that I can leverage existing rails applications for ERD modeling
|
20
|
+
|
21
|
+
- Use Meta Programming and re-implement ActiveRecord::Base
|
22
|
+
|
23
|
+
### Tasks next on list
|
24
|
+
|
25
|
+
Refactor / Simply
|
26
|
+
|
27
|
+
- Replace complex objects an with structs for ancillary data structures such as investigate
|
28
|
+
|
29
|
+
User acceptance testing
|
30
|
+
|
31
|
+
- Provide sample printers for each data structure to visually check data is loading
|
32
|
+
- Point raw_db_schema loader towards a complex ERD and check how it performs
|
33
|
+
|
34
|
+
## Stories and tasks
|
35
|
+
|
36
|
+
### Tasks - completed
|
37
|
+
|
38
|
+
Setup RubyGems and RubyDoc
|
39
|
+
|
40
|
+
- Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_domain)
|
41
|
+
- Attach documentation to [rubydoc.info](https://rubydoc.info/github/to-do-/k_domain/master)
|
42
|
+
|
43
|
+
Setup project management, requirement and SCRUM documents
|
44
|
+
|
45
|
+
- Setup readme file
|
46
|
+
- Setup user stories and tasks
|
47
|
+
- Setup a project backlog
|
48
|
+
- Setup an examples/usage document
|
49
|
+
|
50
|
+
Setup GitHub Action (test and lint)
|
51
|
+
|
52
|
+
- Setup Rspec action
|
53
|
+
- Setup RuboCop action
|
54
|
+
|
55
|
+
Setup new Ruby GEM
|
56
|
+
|
57
|
+
- Build out a standard GEM structure
|
58
|
+
- Add automated semantic versioning
|
59
|
+
- Add Rspec unit testing framework
|
60
|
+
- Add RuboCop linting
|
61
|
+
- Add Guard for automatic watch and test
|
62
|
+
- Add GitFlow support
|
63
|
+
- Add GitHub Repository
|
data/USAGE.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# K Domain
|
2
|
+
|
3
|
+
> K Domain builds complex domain schemas by combining the database schema with a rich entity relationship DSLs
|
4
|
+
|
5
|
+
As an Application Developer, I need a rich and configurable ERD schema, so I can generate enterprise applications quickly
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
### Sample Classes
|
10
|
+
|
11
|
+
#### Simple example
|
12
|
+
|
13
|
+
Description for a simple example that shows up in the USAGE.MD
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class SomeRuby
|
17
|
+
def initialize; end
|
18
|
+
end
|
19
|
+
```
|
data/k_domain.gemspec
CHANGED
@@ -33,10 +33,14 @@ Gem::Specification.new do |spec|
|
|
33
33
|
f.match(%r{^(test|spec|features)/})
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
36
37
|
spec.bindir = 'exe'
|
37
38
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
38
39
|
spec.require_paths = ['lib']
|
39
40
|
# spec.extensions = ['ext/k_domain/extconf.rb']
|
40
41
|
|
42
|
+
spec.add_dependency 'activesupport' , '~> 6'
|
43
|
+
spec.add_dependency 'dry-struct', '~> 1'
|
41
44
|
spec.add_dependency 'k_log' , '~> 0.0.0'
|
45
|
+
spec.add_dependency 'peeky' , '~> 0.0.0'
|
42
46
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Annotates the original schema with methods that implement existing method calls
|
4
|
+
# that are already in the schema so that we can build a hash.
|
5
|
+
#
|
6
|
+
# Writes a new annotated schema.rb file with a public method called load that
|
7
|
+
# builds the hash
|
8
|
+
|
9
|
+
module KDomain
|
10
|
+
module DomainModel
|
11
|
+
class Load
|
12
|
+
include KLog::Logging
|
13
|
+
|
14
|
+
attr_reader :source_file
|
15
|
+
attr_reader :data
|
16
|
+
|
17
|
+
def initialize(source_file)
|
18
|
+
@source_file = source_file
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
json = File.read(source_file)
|
23
|
+
data = KUtil.data.json_parse(json, as: :hash_symbolized)
|
24
|
+
|
25
|
+
@data = KDomain::Schemas::DomainModel.new(data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Loads the db schema object and works through a series of enrichment steps to
|
4
|
+
# that builds the domain modal
|
5
|
+
|
6
|
+
module KDomain
|
7
|
+
module DomainModel
|
8
|
+
class Transform
|
9
|
+
include KLog::Logging
|
10
|
+
|
11
|
+
attr_reader :db_schema
|
12
|
+
attr_reader :target_step_file
|
13
|
+
attr_reader :target_file
|
14
|
+
attr_reader :erd_path
|
15
|
+
|
16
|
+
def initialize(db_schema: , target_file: , target_step_file: , erd_path:)
|
17
|
+
@db_schema = db_schema
|
18
|
+
@target_step_file = target_step_file
|
19
|
+
@target_file = target_file
|
20
|
+
@erd_path = erd_path
|
21
|
+
end
|
22
|
+
|
23
|
+
def call
|
24
|
+
valid = true
|
25
|
+
valid &&= step1
|
26
|
+
valid &&= step2
|
27
|
+
valid &&= step3
|
28
|
+
valid &&= step4
|
29
|
+
valid &&= step5
|
30
|
+
valid &&= step8 # NOT SURE WHERE THIS BELONGS
|
31
|
+
|
32
|
+
raise 'DomainModal transform failed' unless valid
|
33
|
+
|
34
|
+
write
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def step1
|
40
|
+
Step1AttachDbSchema.run(domain_data, db_schema: db_schema)
|
41
|
+
write(step: '1-attach-db-schema')
|
42
|
+
end
|
43
|
+
|
44
|
+
def step2
|
45
|
+
Step2AttachModels.run(domain_data, erd_path: erd_path)
|
46
|
+
write(step: '2-attach-model')
|
47
|
+
end
|
48
|
+
|
49
|
+
def step3
|
50
|
+
Step3AttachColumns.run(domain_data)
|
51
|
+
write(step: '3-attach-columns')
|
52
|
+
end
|
53
|
+
|
54
|
+
def step4
|
55
|
+
Step4AttachErdFiles.run(domain_data, erd_path: erd_path)
|
56
|
+
write(step: '4-attach-erd-files')
|
57
|
+
end
|
58
|
+
|
59
|
+
def step5
|
60
|
+
Step5AttachDictionary.run(domain_data, erd_path: erd_path)
|
61
|
+
write(step: '5-attach-dictionary')
|
62
|
+
end
|
63
|
+
|
64
|
+
def step8
|
65
|
+
Step8LocateRailsModels.run(domain_data, erd_path: erd_path)
|
66
|
+
write(step: '8-rails-files-models')
|
67
|
+
end
|
68
|
+
|
69
|
+
def write(step: nil)
|
70
|
+
file = if step.nil?
|
71
|
+
target_file
|
72
|
+
else
|
73
|
+
format(target_step_file, step: step)
|
74
|
+
end
|
75
|
+
FileUtils.mkdir_p(File.dirname(file))
|
76
|
+
File.write(file, JSON.pretty_generate(domain_data))
|
77
|
+
end
|
78
|
+
|
79
|
+
def domain_data
|
80
|
+
# The initial domain model structure is created here, but populated during the workflows.
|
81
|
+
@domain_data ||= {
|
82
|
+
domain: {
|
83
|
+
models: [],
|
84
|
+
erd_files: [],
|
85
|
+
},
|
86
|
+
rails: {
|
87
|
+
models: [],
|
88
|
+
controllers: [],
|
89
|
+
},
|
90
|
+
rails_resource: {
|
91
|
+
models: [],
|
92
|
+
controllers: [],
|
93
|
+
},
|
94
|
+
dictionary: {
|
95
|
+
items: []
|
96
|
+
},
|
97
|
+
database: {
|
98
|
+
tables: [],
|
99
|
+
indexes: [],
|
100
|
+
foreign_keys: [],
|
101
|
+
meta: {}
|
102
|
+
},
|
103
|
+
investigate: {
|
104
|
+
issues: []
|
105
|
+
}
|
106
|
+
}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The require order is important due to dependencies
|
4
|
+
require_relative './step'
|
5
|
+
require_relative './step1_attach_db_schema'
|
6
|
+
require_relative './step2_attach_models'
|
7
|
+
require_relative './step3_attach_columns'
|
8
|
+
require_relative './step4_attach_erd_files'
|
9
|
+
require_relative './step5_attach_dictionary'
|
10
|
+
require_relative './step8_locate_rails_models'
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module DomainModel
|
5
|
+
class Step
|
6
|
+
include KLog::Logging
|
7
|
+
|
8
|
+
attr_reader :domain_data
|
9
|
+
attr_reader :opts
|
10
|
+
attr_reader :valid
|
11
|
+
alias valid? valid
|
12
|
+
|
13
|
+
def initialize(domain_data, **opts)
|
14
|
+
# Useful for debugging
|
15
|
+
# log.info "Initialize #{self.class.name}"
|
16
|
+
|
17
|
+
@domain_data = domain_data
|
18
|
+
@opts = opts
|
19
|
+
@valid = true
|
20
|
+
end
|
21
|
+
|
22
|
+
def call; end
|
23
|
+
|
24
|
+
def self.run(domain_data, **opts)
|
25
|
+
step = new(domain_data, **opts)
|
26
|
+
step.call
|
27
|
+
step
|
28
|
+
end
|
29
|
+
|
30
|
+
def guard(message)
|
31
|
+
log.error message
|
32
|
+
@valid = false
|
33
|
+
end
|
34
|
+
|
35
|
+
# Domain Model Accessor/Helpers
|
36
|
+
def domain
|
37
|
+
guard('domain is missing') if domain_data[:domain].nil?
|
38
|
+
|
39
|
+
domain_data[:domain]
|
40
|
+
end
|
41
|
+
|
42
|
+
def domain_models
|
43
|
+
domain[:models]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Rails File Accessor/Helpers
|
47
|
+
def rails_resource
|
48
|
+
guard('rails_resource is missing') if domain_data[:rails_resource].nil?
|
49
|
+
|
50
|
+
domain_data[:rails_resource]
|
51
|
+
end
|
52
|
+
|
53
|
+
def rails_resource_models
|
54
|
+
rails_resource[:models]
|
55
|
+
end
|
56
|
+
|
57
|
+
def rails_resource_models=(value)
|
58
|
+
rails_resource[:models] = value
|
59
|
+
end
|
60
|
+
|
61
|
+
def rails_resource_controllers
|
62
|
+
rails_resource[:controllers]
|
63
|
+
end
|
64
|
+
|
65
|
+
# Database Accessor/Helpers
|
66
|
+
def database=(value)
|
67
|
+
domain_data[:database] = value
|
68
|
+
end
|
69
|
+
|
70
|
+
def database
|
71
|
+
guard('database is missing') if domain_data[:database].nil?
|
72
|
+
|
73
|
+
domain_data[:database]
|
74
|
+
end
|
75
|
+
|
76
|
+
def database_tables
|
77
|
+
guard('database_tables is missing') if database[:tables].nil?
|
78
|
+
|
79
|
+
database[:tables]
|
80
|
+
end
|
81
|
+
|
82
|
+
def database_foreign_keys
|
83
|
+
guard('database_foreign_keys is missing') if database[:foreign_keys].nil?
|
84
|
+
|
85
|
+
database[:foreign_keys]
|
86
|
+
end
|
87
|
+
|
88
|
+
def find_table_for_model(model)
|
89
|
+
database_tables.find { |table| table[:name] == model[:table_name] }
|
90
|
+
end
|
91
|
+
|
92
|
+
def table_name_exist?(table_name)
|
93
|
+
if table_name.nil?
|
94
|
+
guard('table_name_exist? was provided with a table_name: nil')
|
95
|
+
return false
|
96
|
+
end
|
97
|
+
database_table_name_hash.key?(table_name)
|
98
|
+
end
|
99
|
+
|
100
|
+
def find_foreign_table(lhs_table_name, column_name)
|
101
|
+
fk = database_foreign_keys.find { |foreign_key| foreign_key[:left] == lhs_table_name && foreign_key[:column] == column_name }
|
102
|
+
return fk[:right] if fk
|
103
|
+
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def investigate(step:, location:, key:, message:)
|
108
|
+
unique_key = build_key(step, location, key)
|
109
|
+
|
110
|
+
return if issue_hash.key?(unique_key)
|
111
|
+
|
112
|
+
value = { step: step, location: location, key: key, message: message }
|
113
|
+
|
114
|
+
issues << value # list
|
115
|
+
issue_hash[unique_key] = value # lookup
|
116
|
+
end
|
117
|
+
|
118
|
+
def issues
|
119
|
+
domain_data[:investigate][:issues]
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def database_table_name_hash
|
125
|
+
@database_table_name_hash ||= database_tables.to_h { |table| [table[:name], table[:name]] }
|
126
|
+
end
|
127
|
+
|
128
|
+
def build_key(*values)
|
129
|
+
values.join('-')
|
130
|
+
end
|
131
|
+
|
132
|
+
def issue_hash
|
133
|
+
return @issue_hash if defined? @issue_hash
|
134
|
+
|
135
|
+
@issue_hash = issues.to_h do |issue|
|
136
|
+
unique_key = build_key(issue[:step], issue[:location], issue[:key])
|
137
|
+
[unique_key, issue]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module DomainModel
|
5
|
+
class Step1AttachDbSchema < KDomain::DomainModel::Step
|
6
|
+
# Map database schema to domain model
|
7
|
+
def call
|
8
|
+
raise 'Schema not supplied' if opts[:db_schema].nil?
|
9
|
+
|
10
|
+
self.database = opts[:db_schema].clone
|
11
|
+
|
12
|
+
guard('tables are missing') if database[:tables].nil?
|
13
|
+
guard('indexes are missing') if database[:indexes].nil?
|
14
|
+
guard('foreign keys are missing') if database[:foreign_keys].nil?
|
15
|
+
guard('rails version is missing') if database[:meta][:rails].nil?
|
16
|
+
guard('postgres extensions are missing') if database[:meta][:db_info][:extensions].nil?
|
17
|
+
guard('unique keys are missing') if database[:meta][:unique_keys].nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Loop through the db_schema tables and build up a
|
4
|
+
# basic model for each table
|
5
|
+
class Step2AttachModels < KDomain::DomainModel::Step
|
6
|
+
# Map database schema to domain model
|
7
|
+
def call
|
8
|
+
raise 'ERD path not supplied' if opts[:erd_path].nil?
|
9
|
+
|
10
|
+
# Schema is re-shaped into a format designed for domain modeling
|
11
|
+
domain[:models] = database_tables.map { |table| model(table) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def model(table)
|
15
|
+
table_name = table[:name].to_s
|
16
|
+
model_name = table_name.singularize
|
17
|
+
|
18
|
+
{
|
19
|
+
name: model_name,
|
20
|
+
name_plural: table_name, # need to check if this is correct as I know it is wrong for account_history_datum
|
21
|
+
table_name: table_name,
|
22
|
+
pk: primary_key(table),
|
23
|
+
erd_location: location(table_name, model_name),
|
24
|
+
statistics: {}, # Load in future step
|
25
|
+
columns: [] # Load in future step
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def primary_key(table)
|
30
|
+
{
|
31
|
+
name: table[:primary_key],
|
32
|
+
type: table[:primary_key_type],
|
33
|
+
exist: !table[:primary_key].nil?
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Location of source code
|
38
|
+
def location(table_name, model_name)
|
39
|
+
file_normal = File.join(opts[:erd_path], "#{model_name}.rb")
|
40
|
+
file_custom = File.join(opts[:erd_path], "#{table_name}.rb")
|
41
|
+
file_exist = true
|
42
|
+
state = []
|
43
|
+
|
44
|
+
if File.exist?(file_normal)
|
45
|
+
file = file_normal
|
46
|
+
state.push(:has_ruby_model)
|
47
|
+
elsif File.exist?(file_custom)
|
48
|
+
file = file_custom
|
49
|
+
state.push(:has_ruby_model)
|
50
|
+
state.push(:nonconventional_name)
|
51
|
+
else
|
52
|
+
file = ''
|
53
|
+
file_exist = false
|
54
|
+
end
|
55
|
+
|
56
|
+
{
|
57
|
+
file: file,
|
58
|
+
exist: file_exist,
|
59
|
+
state: state # display_state: state.join(' ')
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|