k_domain 0.0.20 → 0.0.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.builders/boot.rb +40 -0
  3. data/.builders/generators/configuration_generator.rb +22 -0
  4. data/.builders/run.rb +16 -0
  5. data/.github/workflows/main.yml +5 -3
  6. data/.gitignore +2 -0
  7. data/.rubocop.yml +9 -5
  8. data/Gemfile +1 -1
  9. data/Guardfile +1 -0
  10. data/README.md +15 -0
  11. data/k_domain.gemspec +1 -1
  12. data/lib/k_domain/config/_.rb +4 -0
  13. data/lib/k_domain/config/config.rb +19 -0
  14. data/lib/k_domain/config/configuration.rb +76 -0
  15. data/lib/k_domain/domain_model/build_rich_models.rb +64 -0
  16. data/lib/k_domain/domain_model/load.rb +44 -1
  17. data/lib/k_domain/domain_model/transform.rb +28 -16
  18. data/lib/k_domain/domain_model/transform_steps/_.rb +7 -5
  19. data/lib/k_domain/domain_model/transform_steps/step.rb +20 -0
  20. data/lib/k_domain/domain_model/transform_steps/{step1_attach_db_schema.rb → step1_db_schema.rb} +2 -1
  21. data/lib/k_domain/domain_model/transform_steps/{step6_attach_dictionary.rb → step20_dictionary.rb} +6 -6
  22. data/lib/k_domain/domain_model/transform_steps/step2_domain_models.rb +123 -0
  23. data/lib/k_domain/domain_model/transform_steps/step4_rails_resource_models.rb +3 -3
  24. data/lib/k_domain/domain_model/transform_steps/step5_rails_resource_routes.rb +36 -0
  25. data/lib/k_domain/domain_model/transform_steps/step6_rails_structure_models.rb +91 -0
  26. data/lib/k_domain/domain_model/transform_steps/step7_rails_structure_controllers.rb +114 -0
  27. data/lib/k_domain/domain_model/transform_steps/step8_domain_columns.rb +99 -0
  28. data/lib/k_domain/queries/_.rb +4 -0
  29. data/lib/k_domain/queries/base_query.rb +13 -0
  30. data/lib/k_domain/queries/domain_model_query.rb +88 -0
  31. data/lib/k_domain/rails_code_extractor/_.rb +5 -0
  32. data/lib/k_domain/rails_code_extractor/extract_controller.rb +61 -0
  33. data/lib/k_domain/rails_code_extractor/extract_model.rb +21 -8
  34. data/lib/k_domain/rails_code_extractor/shim_loader.rb +4 -1
  35. data/lib/k_domain/raw_db_schema/load.rb +1 -1
  36. data/lib/k_domain/raw_db_schema/transform.rb +28 -3
  37. data/lib/k_domain/schemas/_.rb +5 -3
  38. data/lib/k_domain/schemas/database.rb +86 -0
  39. data/lib/k_domain/schemas/domain/erd_file.rb +78 -77
  40. data/lib/k_domain/schemas/domain.rb +153 -0
  41. data/lib/k_domain/schemas/{domain/_.rb → domain_types.rb} +1 -8
  42. data/lib/k_domain/schemas/{domain_model.rb → main_dataset.rb} +4 -4
  43. data/lib/k_domain/schemas/rails_resource.rb +43 -6
  44. data/lib/k_domain/schemas/rails_structure.rb +104 -14
  45. data/lib/k_domain/version.rb +1 -1
  46. data/lib/k_domain.rb +7 -3
  47. data/templates/custom/action_controller.rb +7 -0
  48. data/templates/custom/controller_interceptors.rb +80 -0
  49. data/templates/custom/model_interceptors.rb +95 -0
  50. data/templates/load_schema.rb +7 -0
  51. data/templates/rails/action_controller.rb +301 -0
  52. data/templates/{active_record_shims.rb → rails/active_record.rb} +23 -41
  53. data/templates/ruby_code_extractor/attach_class_info.rb +13 -0
  54. data/templates/ruby_code_extractor/behaviour_accessors.rb +39 -0
  55. data/templates/sample_config.rb +47 -0
  56. data/templates/simple/controller_interceptors.rb +2 -0
  57. metadata +36 -21
  58. data/lib/k_domain/domain_model/transform_steps/step2_attach_models.rb +0 -62
  59. data/lib/k_domain/domain_model/transform_steps/step3_attach_columns.rb +0 -137
  60. data/lib/k_domain/domain_model/transform_steps/step5_rails_models.rb +0 -71
  61. data/lib/k_domain/schemas/database/_.rb +0 -7
  62. data/lib/k_domain/schemas/database/foreign_key.rb +0 -14
  63. data/lib/k_domain/schemas/database/index.rb +0 -14
  64. data/lib/k_domain/schemas/database/schema.rb +0 -31
  65. data/lib/k_domain/schemas/database/table.rb +0 -32
  66. data/lib/k_domain/schemas/domain/domain.rb +0 -11
  67. data/lib/k_domain/schemas/domain/models/column.rb +0 -49
  68. data/lib/k_domain/schemas/domain/models/model.rb +0 -111
  69. data/templates/fake_module_shims.rb +0 -42
@@ -1,137 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Attach columns to models
4
- class Step3AttachColumns < KDomain::DomainModel::Step
5
- attr_accessor :table
6
- attr_reader :column_name
7
- attr_reader :column_symbol
8
-
9
- def call
10
- build_columns
11
- end
12
-
13
- def build_columns
14
- domain_models.each do |model|
15
- @table = find_table_for_model(model)
16
- columns = columns(table[:columns])
17
- columns = insert_primary_key(model, columns)
18
- model[:columns] = columns
19
- end
20
- end
21
-
22
- def column_data(name)
23
- @column_name = name
24
- @column_symbol = name.to_sym
25
- {
26
- name: name,
27
- name_plural: name.pluralize,
28
- type: nil,
29
- precision: nil,
30
- scale: nil,
31
- default: nil,
32
- null: nil,
33
- limit: nil,
34
- array: nil
35
- }
36
- end
37
-
38
- def columns(db_columns)
39
- db_columns.map do |db_column|
40
- column = column_data(db_column[:name]).merge(
41
- type: check_type(db_column[:type]),
42
- precision: db_column[:precision],
43
- scale: db_column[:scale],
44
- default: db_column[:default],
45
- null: db_column[:null],
46
- limit: db_column[:limit],
47
- array: db_column[:array]
48
- )
49
-
50
- expand_column(column)
51
- end
52
- end
53
-
54
- def insert_primary_key(model, columns)
55
- return columns unless model[:pk][:exist]
56
-
57
- column = column_data('id').merge(
58
- type: check_type(model[:pk][:type])
59
- )
60
-
61
- columns.unshift(expand_column(column))
62
- columns
63
- end
64
-
65
- def expand_column(column)
66
- foreign_table = lookup_foreign_table(column_name)
67
- is_foreign = !foreign_table.nil?
68
- # is_foreign = foreign_key?(column_name)
69
- structure_type = structure_type(is_foreign)
70
-
71
- column.merge({
72
- structure_type: structure_type,
73
- foreign_key: is_foreign,
74
- foreign_table: (foreign_table || '').singularize,
75
- foreign_table_plural: (foreign_table || '').pluralize
76
- })
77
- end
78
-
79
- def check_type(type)
80
- type = type.to_sym if type.is_a?(String)
81
-
82
- return type if %i[string integer bigint bigserial boolean float decimal datetime date hstore text jsonb].include?(type)
83
-
84
- if type.nil?
85
- guard('nil type detected for db_column[:type]')
86
-
87
- return :string
88
- end
89
-
90
- guard("new type detected for db_column[:type] - #{type}")
91
-
92
- camel.parse(type.to_s).downcase
93
- end
94
-
95
- def lookup_foreign_table(column_name)
96
- foreign_table = find_foreign_table(table[:name], column_name)
97
-
98
- return foreign_table if foreign_table
99
-
100
- cn = column_name.to_s
101
-
102
- if cn.ends_with?('_id')
103
- table_name = column_name[0..-4]
104
- table_name_plural = table_name.pluralize
105
-
106
- if table_name_exist?(table_name_plural.to_s)
107
- investigate(step: :step3_attach_columns,
108
- location: :lookup_foreign_table,
109
- key: column_name,
110
- message: "#{@table[:name]}.#{column_name} => #{table_name_plural} - Relationship not found in DB, so have inferred this relationship. You may want to check that this relation is correct")
111
-
112
- return table_name
113
- end
114
-
115
- investigate(step: :step3_attach_columns,
116
- location: :lookup_foreign_table,
117
- key: column_name,
118
- message: "#{@table[:name]}.#{column_name} => #{table_name_plural} - Table not found for a column that looks like foreign_key")
119
- end
120
-
121
- nil
122
- end
123
-
124
- # Need some configurable data dictionary where by
125
- # _token can be setup on a project by project basis
126
- def structure_type(is_foreign)
127
- return :foreign_key if is_foreign
128
- return :primary_key if column_symbol == :id
129
- return :timestamp if column_symbol == :created_at || column_symbol == :updated_at
130
- return :timestamp if column_symbol == :created_at || column_symbol == :updated_at
131
- return :deleted_at if column_symbol == :deleted_at
132
- return :encrypted_password if column_symbol == :encrypted_password
133
- return :token if column_name.ends_with?('_token') || column_name.ends_with?('_token_iv')
134
-
135
- :data
136
- end
137
- end
@@ -1,71 +0,0 @@
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 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # The require order is important due to dependencies
4
- require_relative './index'
5
- require_relative './table'
6
- require_relative './foreign_key'
7
- require_relative './schema'
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module KDomain
4
- module Database
5
- class ForeignKey < Dry::Struct
6
- attribute :left , Types::Strict::String
7
- attribute :right , Types::Strict::String
8
- attribute :name? , Types::Strict::String.optional.default(nil)
9
- attribute :on_update? , Types::Strict::String.optional.default(nil)
10
- attribute :on_delete? , Types::Strict::String.optional.default(nil)
11
- attribute :column? , Types::Strict::String.optional.default(nil)
12
- end
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module KDomain
4
- module Database
5
- class Index < Dry::Struct
6
- attribute :name , Types::Strict::String
7
- attribute :fields , Types::Nominal::Any.optional.default('xxxxx1')
8
- attribute :using , Types::Nominal::String
9
- attribute :order? , Types::Nominal::Hash
10
- attribute :where? , Types::Nominal::Any.optional.default(nil)
11
- attribute :unique? , Types::Nominal::Any.optional.default(nil)
12
- end
13
- end
14
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module KDomain
4
- module Database
5
- class Schema < Dry::Struct
6
- class DbInfo < Dry::Struct
7
- attribute :type , Types::Strict::String
8
- attribute :version , Types::Nominal::Any.optional.default(nil)
9
- attribute :extensions , Types::Strict::Array
10
- end
11
-
12
- class UniqueKey < Dry::Struct
13
- attribute :type , Types::Strict::String
14
- attribute :category , Types::Strict::String.optional
15
- attribute :key , Types::Strict::String
16
- attribute :keys , Types::Strict::Array
17
- end
18
-
19
- class Meta < Dry::Struct
20
- attribute :rails , Types::Strict::Integer
21
- attribute :db_info , KDomain::Database::Schema::DbInfo
22
- attribute :unique_keys , Types::Strict::Array.of(KDomain::Database::Schema::UniqueKey)
23
- end
24
-
25
- attribute :tables , Types::Strict::Array.of(KDomain::Database::Table)
26
- attribute :foreign_keys? , Types::Strict::Array.of(KDomain::Database::ForeignKey)
27
- attribute :indexes? , Types::Strict::Array.of(KDomain::Database::Index)
28
- attribute :meta , KDomain::Database::Schema::Meta
29
- end
30
- end
31
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module KDomain
4
- module Database
5
- class Table < Dry::Struct
6
- class RailsSchema < Dry::Struct
7
- attribute :primary_key , Types::Nominal::Any.optional.default(nil)
8
- attribute :id , Types::Nominal::Any.optional.default(nil)
9
- attribute :force , Types::Nominal::Any.optional.default(nil)
10
- end
11
-
12
- class Column < Dry::Struct
13
- attribute :name , Types::Strict::String
14
- attribute :type , Types::Strict::String
15
- attribute :precision? , Types::Strict::Integer.optional.default(nil)
16
- attribute :scale? , Types::Strict::Integer.optional.default(nil)
17
- attribute :default? , Types::Nominal::Any.optional.default(nil)
18
- attribute :array? , Types::Strict::Bool.optional.default(nil)
19
- attribute :null? , Types::Strict::Bool.optional.default(nil)
20
- attribute :limit? , Types::Strict::Integer.optional.default(nil)
21
- end
22
-
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
- end
31
- end
32
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Domain class holds a list of the entities
4
- module KDomain
5
- module DomainModel
6
- class Domain < Dry::Struct
7
- attribute :models , Types::Strict::Array.of(KDomain::DomainModel::Model)
8
- # attribute :erd_files , Types::Strict::Array.of(KDomain::DomainModel::ErdFile)
9
- end
10
- end
11
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module KDomain
4
- module DomainModel
5
- class Column < Dry::Struct
6
- attribute :name , Types::Strict::String # "source_account_id"
7
- attribute :name_plural , Types::Strict::String # "source_account_ids"
8
- attribute :type , Types::Coercible::Symbol # "integer"
9
- attribute :precision , Types::Strict::Integer.optional.default(nil) # null
10
- attribute :scale , Types::Strict::Integer.optional.default(nil) # null
11
- attribute :default , Types::Nominal::Any.optional.default(nil) # null
12
- attribute :null , Types::Nominal::Any.optional.default(nil) # null
13
- attribute :limit , Types::Strict::Integer.optional.default(nil) # null
14
- attribute :array , Types::Strict::Bool.optional.default(nil) # null
15
-
16
- # Calculated value
17
- attribute :structure_type , Types::Coercible::Symbol #
18
- attribute :foreign_key , Types::Strict::Bool.optional.default(nil) #
19
- attribute :foreign_table , Types::Strict::String #
20
- attribute :foreign_table_plural , Types::Strict::String #
21
-
22
- # def data_column
23
- # @columns_data ||= structure_type?(:data)
24
- # end
25
-
26
- # def structure_type?(*structure_types)
27
- # structure_types.include?(column.structure_type)
28
- # end
29
-
30
- def db_type
31
- return @db_type if defined? @db_type
32
-
33
- @db_type = DB_TYPE[type] || '******'
34
- end
35
-
36
- def ruby_type
37
- return @ruby_type if defined? @ruby_type
38
-
39
- @ruby_type = RUBY_TYPE[type] || '******'
40
- end
41
-
42
- def csharp_type
43
- return @csharp_type if defined? @csharp_type
44
-
45
- @csharp_type = CSHARP_TYPE[type] || '******'
46
- end
47
- end
48
- end
49
- end
@@ -1,111 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Domain class holds a list of the entities
4
- module KDomain
5
- module DomainModel
6
- class Model < Dry::Struct
7
- class Pk < Dry::Struct
8
- attribute :name , Types::Strict::String.optional.default(nil)
9
- attribute :type , Types::Strict::String.optional.default(nil)
10
- attribute :exist , Types::Strict::Bool
11
- end
12
-
13
- class ErdLocation < Dry::Struct
14
- attribute :file , Types::Strict::String
15
- attribute :exist , Types::Strict::Bool
16
- attribute :state , Types::Strict::Array
17
- end
18
-
19
- attribute :name , Types::Strict::String
20
- attribute :name_plural , Types::Strict::String
21
- attribute :table_name , Types::Strict::String
22
- # Model type - :entity, :basic_user, :admin_user, possibly: m2m, agg_root
23
- attribute :type , Types::Strict::Symbol.optional.default(:entity)
24
- attribute :pk , KDomain::DomainModel::Model::Pk
25
- attribute :erd_location , KDomain::DomainModel::Model::ErdLocation
26
- attribute :columns , Types::Strict::Array.of(KDomain::DomainModel::Column)
27
-
28
- def ruby?
29
- location.exist
30
- end
31
-
32
- def pk?
33
- pk.exist
34
- end
35
-
36
- # If filled in, the model has a main field that is useful for rendering and may be used for unique constraint, may also be called display_name
37
- def main_key
38
- @main_key ||= MainKey.lookup(name, columns_data)
39
- end
40
-
41
- def traits
42
- @traits ||= Traits.lookup(name)
43
- end
44
-
45
- # def where()
46
- # end
47
-
48
- # def columns_where()
49
- # end
50
-
51
- # Column filters
52
-
53
- def columns_data
54
- @columns_data ||= columns_for_structure_types(:data)
55
- end
56
-
57
- # def columns_data_optional
58
- # @columns_data_optional ||= columns_for_structure_types(:data).select { |c| true }
59
- # end
60
-
61
- # def columns_data_required
62
- # @columns_data_required ||= columns_for_structure_types(:data).select { |c| false }
63
- # end
64
-
65
- def columns_primary
66
- @columns_primary ||= columns_for_structure_types(:primary_key)
67
- end
68
-
69
- def columns_foreign
70
- @columns_foreign ||= columns_for_structure_types(:foreign_key)
71
- end
72
-
73
- def columns_timestamp
74
- @columns_data_timestamp ||= columns_for_structure_types(:timestamp)
75
- end
76
-
77
- def columns_deleted_at
78
- @columns_data_deleted_at ||= columns_for_structure_types(:deleted_at)
79
- end
80
-
81
- def columns_virtual
82
- @columns_virtual ||= columns_for_structure_types(:timestamp, :deleted_at)
83
- end
84
-
85
- def columns_data_foreign
86
- @columns_data_foreign ||= columns_for_structure_types(:data, :foreign_key)
87
- end
88
- alias rows_fields_and_fk columns_data_foreign
89
-
90
- def columns_data_primary
91
- @columns_data_primary ||= columns_for_structure_types(:data, :primary_key)
92
- end
93
- alias rows_fields_and_pk columns_data_primary
94
-
95
- def columns_data_virtual
96
- @columns_data_virtual ||= columns_for_structure_types(:data, :timestamp, :deleted_at)
97
- end
98
- alias rows_fields_and_virtual columns_data_virtual
99
-
100
- def columns_data_foreign_virtual
101
- @columns_data_foreign_virtual ||= columns_for_structure_types(:data, :foreign_key, :timestamp, :deleted_at)
102
- end
103
-
104
- private
105
-
106
- def columns_for_structure_types(*structure_types)
107
- columns.select { |column| structure_types.include?(column.structure_type) }
108
- end
109
- end
110
- end
111
- end
@@ -1,42 +0,0 @@
1
- class Rails
2
- def self.env; end
3
-
4
- def self.application
5
- OpenStruct.new(secrets: OpenStruct.new(credentials_secret_key: Base64.encode64('ABC')))
6
- end
7
- end
8
-
9
- module ActsAsCommentable
10
- module Comment
11
- end
12
- end
13
-
14
- module Scopes
15
- module CompanyScopes
16
- end
17
- end
18
-
19
- module ActionView
20
- module Helpers
21
- module NumberHelper
22
- end
23
- end
24
- end
25
-
26
- module RailsUpgrade
27
- def rails4?
28
- true
29
- end
30
-
31
- def rails5?
32
- true
33
- end
34
-
35
- def rails6?
36
- true
37
- end
38
-
39
- def belongs_to_required
40
- {}
41
- end
42
- end