k_domain 0.0.20 → 0.0.23

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.builders/config/_.rb +3 -0
  3. data/.builders/setup.rb +30 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +1 -2
  6. data/Guardfile +1 -0
  7. data/README.md +15 -0
  8. data/lib/k_domain/domain_model/transform.rb +23 -13
  9. data/lib/k_domain/domain_model/transform_steps/_.rb +7 -5
  10. data/lib/k_domain/domain_model/transform_steps/step.rb +20 -0
  11. data/lib/k_domain/domain_model/transform_steps/{step1_attach_db_schema.rb → step1_db_schema.rb} +2 -1
  12. data/lib/k_domain/domain_model/transform_steps/{step6_attach_dictionary.rb → step20_dictionary.rb} +6 -6
  13. data/lib/k_domain/domain_model/transform_steps/step2_domain_models.rb +123 -0
  14. data/lib/k_domain/domain_model/transform_steps/step4_rails_resource_models.rb +3 -3
  15. data/lib/k_domain/domain_model/transform_steps/step5_rails_resource_routes.rb +36 -0
  16. data/lib/k_domain/domain_model/transform_steps/step6_rails_structure_models.rb +90 -0
  17. data/lib/k_domain/domain_model/transform_steps/step7_rails_structure_controllers.rb +109 -0
  18. data/lib/k_domain/domain_model/transform_steps/{step3_attach_columns.rb → step8_domain_columns.rb} +40 -73
  19. data/lib/k_domain/rails_code_extractor/_.rb +5 -0
  20. data/lib/k_domain/rails_code_extractor/extract_controller.rb +59 -0
  21. data/lib/k_domain/rails_code_extractor/extract_model.rb +19 -8
  22. data/lib/k_domain/rails_code_extractor/shim_loader.rb +1 -0
  23. data/lib/k_domain/raw_db_schema/load.rb +1 -1
  24. data/lib/k_domain/raw_db_schema/transform.rb +2 -1
  25. data/lib/k_domain/schemas/_.rb +2 -2
  26. data/lib/k_domain/schemas/database.rb +86 -0
  27. data/lib/k_domain/schemas/domain.rb +154 -0
  28. data/lib/k_domain/schemas/domain_model.rb +2 -2
  29. data/lib/k_domain/schemas/rails_resource.rb +43 -6
  30. data/lib/k_domain/schemas/rails_structure.rb +94 -14
  31. data/lib/k_domain/version.rb +1 -1
  32. data/lib/k_domain.rb +1 -2
  33. data/templates/custom/action_controller.rb +36 -0
  34. data/templates/custom/controller_interceptors.rb +78 -0
  35. data/templates/custom/model_interceptors.rb +71 -0
  36. data/templates/load_schema.rb +7 -0
  37. data/templates/old_printspeek_schema copy.rb +231 -0
  38. data/templates/old_printspeek_schema.rb +233 -0
  39. data/templates/rails/action_controller.rb +301 -0
  40. data/templates/{active_record_shims.rb → rails/active_record.rb} +21 -41
  41. data/templates/ruby_code_extractor/attach_class_info.rb +13 -0
  42. data/templates/ruby_code_extractor/behaviour_accessors.rb +39 -0
  43. data/templates/simple/controller_interceptors.rb +2 -0
  44. metadata +26 -18
  45. data/lib/k_domain/domain_model/transform_steps/step2_attach_models.rb +0 -62
  46. data/lib/k_domain/domain_model/transform_steps/step5_rails_models.rb +0 -71
  47. data/lib/k_domain/schemas/database/_.rb +0 -7
  48. data/lib/k_domain/schemas/database/foreign_key.rb +0 -14
  49. data/lib/k_domain/schemas/database/index.rb +0 -14
  50. data/lib/k_domain/schemas/database/schema.rb +0 -31
  51. data/lib/k_domain/schemas/database/table.rb +0 -32
  52. data/lib/k_domain/schemas/domain/domain.rb +0 -11
  53. data/lib/k_domain/schemas/domain/models/column.rb +0 -49
  54. data/lib/k_domain/schemas/domain/models/model.rb +0 -111
  55. data/templates/fake_module_shims.rb +0 -42
@@ -8,26 +8,26 @@ module KDomain
8
8
  attribute :block? , Types::Strict::String
9
9
  end
10
10
 
11
- class BaseType < Dry::Struct
12
- attribute :name? , Types::Strict::String
11
+ class NameOptsType < Dry::Struct
12
+ attribute :name? , Types::Strict::String | Types::Strict::Bool
13
13
  attribute :opts? , Types::Strict::Hash
14
14
  attribute :block? , Types::Strict::String.optional.default(nil)
15
15
  end
16
16
 
17
- class Scope < KDomain::Schemas::RailsStructure::BaseType
17
+ class OptsType < Dry::Struct
18
+ attribute :opts? , Types::Strict::Hash
18
19
  end
19
20
 
20
- class BelongsTo < KDomain::Schemas::RailsStructure::BaseType
21
- end
21
+ # Model Behaviours
22
+ class Scope < KDomain::Schemas::RailsStructure::NameOptsType; end
22
23
 
23
- class HasOne < KDomain::Schemas::RailsStructure::BaseType
24
- end
24
+ class BelongsTo < KDomain::Schemas::RailsStructure::NameOptsType; end
25
25
 
26
- class HasMany < KDomain::Schemas::RailsStructure::BaseType
27
- end
26
+ class HasOne < KDomain::Schemas::RailsStructure::NameOptsType; end
28
27
 
29
- class HasAndBelongsToMany < KDomain::Schemas::RailsStructure::BaseType
30
- end
28
+ class HasMany < KDomain::Schemas::RailsStructure::NameOptsType; end
29
+
30
+ class HasAndBelongsToMany < KDomain::Schemas::RailsStructure::NameOptsType; end
31
31
 
32
32
  class Validate < Dry::Struct
33
33
  attribute :names? , Types::Array.of(Types::Strict::String)
@@ -35,10 +35,10 @@ module KDomain
35
35
  attribute :block? , Types::Strict::String.optional.default(nil)
36
36
  end
37
37
 
38
- class Validates < KDomain::Schemas::RailsStructure::BaseType
38
+ class Validates < KDomain::Schemas::RailsStructure::NameOptsType
39
39
  end
40
40
 
41
- class Behaviours < Dry::Struct
41
+ class ModelBehaviours < Dry::Struct
42
42
  attribute :class_name? , Types::Strict::String
43
43
  attribute :default_scope? , KDomain::Schemas::RailsStructure::DefaultScope
44
44
  attribute :scopes? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Scope)
@@ -76,15 +76,95 @@ module KDomain
76
76
  attribute :exist , Types::Strict::Bool
77
77
  attribute :state , Types::Strict::String
78
78
  attribute :code , Types::Strict::String
79
- attribute :behaviours? , KDomain::Schemas::RailsStructure::Behaviours
79
+ attribute :behaviours? , KDomain::Schemas::RailsStructure::ModelBehaviours
80
80
  attribute :functions? , KDomain::Schemas::RailsStructure::Functions
81
81
  end
82
82
 
83
+ # Controller Behaviours
84
+ class AfterAction < KDomain::Schemas::RailsStructure::NameOptsType; end
85
+
86
+ class AroundAction < KDomain::Schemas::RailsStructure::NameOptsType; end
87
+
88
+ class BeforeAction < KDomain::Schemas::RailsStructure::NameOptsType; end
89
+
90
+ # rubocop:disable Naming/ClassAndModuleCamelCase
91
+ class Prepend_beforeAction < KDomain::Schemas::RailsStructure::NameOptsType; end
92
+
93
+ class Skip_beforeAction < KDomain::Schemas::RailsStructure::NameOptsType; end
94
+ # rubocop:enable Naming/ClassAndModuleCamelCase
95
+
96
+ class BeforeFilter < KDomain::Schemas::RailsStructure::NameOptsType; end
97
+
98
+ class SkipBeforeFilter < KDomain::Schemas::RailsStructure::NameOptsType; end
99
+
100
+ class Layout < KDomain::Schemas::RailsStructure::NameOptsType; end
101
+
102
+ class HttpBasicAuthenticateWith < KDomain::Schemas::RailsStructure::OptsType; end
103
+
104
+ class ProtectFromForgery < KDomain::Schemas::RailsStructure::OptsType; end
105
+
106
+ class RescueFrom < Dry::Struct
107
+ attribute :type , Types::Strict::String
108
+ end
109
+
110
+ class HelperMethod < Dry::Struct
111
+ attribute :names , Types::Strict::Array.of(Types::Strict::String)
112
+ end
113
+
114
+ class Helper < Dry::Struct
115
+ attribute :name , Types::Strict::String
116
+ end
117
+
118
+ class ControllerBehaviours < Dry::Struct
119
+ attribute :class_name? , Types::Strict::String
120
+ attribute :after_action? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::AfterAction)
121
+ attribute :around_action? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::AroundAction)
122
+ attribute :before_action? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::BeforeAction)
123
+ attribute :prepend_before_action? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Prepend_beforeAction)
124
+ attribute :skip_before_action? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Skip_beforeAction)
125
+ attribute :before_filter? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::BeforeFilter)
126
+ attribute :skip_before_filter? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::SkipBeforeFilter)
127
+ attribute :layout? , KDomain::Schemas::RailsStructure::Layout
128
+ attribute :http_basic_authenticate_with? , KDomain::Schemas::RailsStructure::OptsType
129
+ attribute :protect_from_forgery? , KDomain::Schemas::RailsStructure::OptsType
130
+
131
+ attribute :rescue_from? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::RescueFrom)
132
+ attribute :helper_method? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::HelperMethod)
133
+ attribute :helper? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Helper)
134
+ end
135
+
136
+ class ControllerActions < Dry::Struct
137
+ attribute :route_name? , Types::Strict::String
138
+ attribute :action? , Types::String.optional
139
+ attribute :uri_path? , Types::String
140
+ attribute :mime_match? , Types::String
141
+ attribute :verbs? , Types.Array(Types::Verb)
142
+ end
143
+
83
144
  class Controller < Dry::Struct
145
+ attribute :name , Types::String
146
+ attribute :path , Types::String
147
+ attribute :namespace , Types::String
148
+ attribute :file , Types::String
149
+ attribute :exist , Types::Bool
150
+ attribute :full_file , Types::String
151
+ attribute :behaviours? , KDomain::Schemas::RailsStructure::ControllerBehaviours
152
+ attribute :functions? , KDomain::Schemas::RailsStructure::Functions
153
+ attribute :actions? , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::ControllerActions)
84
154
  end
85
155
 
86
156
  attribute :models , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Model)
87
157
  attribute :controllers , Types::Strict::Array.of(KDomain::Schemas::RailsStructure::Controller)
158
+
159
+ def find_controller(path)
160
+ path = path.to_s
161
+ controllers.find { |controller| controller.path.to_s == path }
162
+ end
163
+
164
+ def find_model(name)
165
+ name = name.to_s
166
+ models.find { |model| model.model_name.to_s == name }
167
+ end
88
168
  end
89
169
  end
90
170
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KDomain
4
- VERSION = '0.0.20'
4
+ VERSION = '0.0.23'
5
5
  end
data/lib/k_domain.rb CHANGED
@@ -11,8 +11,7 @@ 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/shim_loader'
15
- require 'k_domain/rails_code_extractor/extract_model'
14
+ require 'k_domain/rails_code_extractor/_'
16
15
 
17
16
  # # This is useful if you want to initialize structures via Hash
18
17
  # class SymbolizeStruct < Dry::Struct
@@ -0,0 +1,36 @@
1
+ module ActionController
2
+ class Base
3
+ def self.require(require)
4
+ add(:require, require)
5
+ end
6
+ # def self.rescue_from(type)#, &block)
7
+ # # block_source = nil
8
+ # # block_source = lambda_source(block, 'default_scope') if block_given?
9
+
10
+ # add(:rescue_from, {
11
+ # type: type#,
12
+ # # block: block_source
13
+ # })
14
+ # end
15
+ # def self.helper_method(*names)
16
+ # add(:helper_method, {
17
+ # names: names
18
+ # })
19
+ # end
20
+ # def self.helper(name)
21
+ # add(:helper, {
22
+ # name: name
23
+ # })
24
+ # end
25
+ # def self.http_basic_authenticate_with(**opts)
26
+ # add(:http_basic_authenticate_with, {
27
+ # opts: opts
28
+ # })
29
+ # end
30
+ # def self.protect_from_forgery(**opts)
31
+ # add(:protect_from_forgery, {
32
+ # opts: opts
33
+ # })
34
+ # end
35
+ end
36
+ end
@@ -0,0 +1,78 @@
1
+ class Rails
2
+ def self.env; end
3
+
4
+ def self.application
5
+ OpenStruct.new(
6
+ secrets: OpenStruct.new(
7
+ credentials_secret_key: Base64.encode64('ABC'),
8
+ aws_secret_access_key: Base64.encode64('ABC')
9
+ )
10
+ )
11
+ end
12
+ end
13
+ class RegionConfig
14
+ def self.require_value(*_p, **_o, &block); end
15
+ end
16
+
17
+ class ApplicationController < ActionController::Base
18
+ end
19
+
20
+ module Admin
21
+ class BaseController < ActionController::Base
22
+ end
23
+ end
24
+
25
+ module Api
26
+ module V1
27
+ class BaseController < ActionController::Base
28
+ end
29
+ end
30
+ end
31
+
32
+ module Enterprises
33
+ class BaseController < ActionController::Base
34
+ end
35
+ end
36
+
37
+ module Portal
38
+ class BaseController < ApplicationController
39
+ end
40
+ end
41
+
42
+ module ActiveRecord
43
+ class RecordNotFound
44
+ end
45
+ end
46
+
47
+ module Aws
48
+ class Credentials
49
+ def initialize(*_p, **_o, &block); end
50
+ end
51
+ module S3
52
+ class Client
53
+ def initialize(*_p, **_o, &block); end
54
+ end
55
+ end
56
+ end
57
+
58
+ module Devise
59
+ class SessionsController < ActionController::Base
60
+ end
61
+ class Mapping
62
+ def self.find_scope!(*_p, **_o); end
63
+ end
64
+ end
65
+
66
+ module Respondable; end
67
+ module ContactUpdateable; end
68
+ module SalesRepUpdateable; end
69
+ module MIME; end
70
+ module MaterialIconsHelper; end
71
+ module LocationUpdateable; end
72
+ module WantedByUpdateable; end
73
+ module FollowUpUpdateable; end
74
+ module EstimateArchiveUpdateable; end
75
+ module ContextContactUpdateable; end
76
+ module ProofDateUpdateable; end
77
+ module PoUpdateable; end
78
+ module SalesRepUpdateable; end
@@ -0,0 +1,71 @@
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
+ class Thread
20
+ def initialize(*_p, **_o, &block); end
21
+ end
22
+
23
+ class ApplicationRecord < ActiveRecord::Base
24
+ end
25
+
26
+ class Email < ActiveRecord::Base
27
+ def self.ses_send(*_p, **_o); end
28
+ end
29
+
30
+ module Emails
31
+ class Task
32
+ def new_task(*_p, **_o); end
33
+ end
34
+ class Salesrep
35
+ def change_sales_rep(*_p, **_o); end
36
+ end
37
+ end
38
+
39
+ module EstimateConvertable; end
40
+ module ApiLoggable; end
41
+ module Excludable; end
42
+ module Bookmarkable; end
43
+ module Categorizable; end
44
+ module PgSearch; end
45
+ module Excludable; end
46
+ module JsonbStore; end
47
+
48
+ module ActionView
49
+ module Helpers
50
+ module NumberHelper
51
+ end
52
+ end
53
+ end
54
+
55
+ module RailsUpgrade
56
+ def rails4?
57
+ true
58
+ end
59
+
60
+ def rails5?
61
+ true
62
+ end
63
+
64
+ def rails6?
65
+ true
66
+ end
67
+
68
+ def belongs_to_required
69
+ {}
70
+ end
71
+ end
@@ -1,6 +1,7 @@
1
1
  class LoadSchema
2
2
  attr_reader :schema
3
3
 
4
+ # XMEN
4
5
  def initialize
5
6
  @unique_keys = {}
6
7
  @current_table = nil
@@ -9,6 +10,7 @@ class LoadSchema
9
10
  tables: [],
10
11
  foreign_keys: [],
11
12
  indexes: [],
13
+ views: [],
12
14
  meta: {
13
15
  rails: @rails_version,
14
16
  db_info: {
@@ -131,6 +133,11 @@ class LoadSchema
131
133
  add_index(name, fields, **opts)
132
134
  end
133
135
 
136
+ def create_view(name, **opts)
137
+ row = { name: name, **opts }
138
+ schema[:views] << row
139
+ add_unique_keys(row.keys, type: :views)
140
+ end
134
141
 
135
142
  def add_foreign_key(left_table, right_table, **opts)
136
143
  # puts "add_foreign_key(#{left_table}, #{right_table})"
@@ -0,0 +1,231 @@
1
+ # Store the raw schema for the tables that are used in the original PrintSpeak database
2
+ class SchemaPrintspeak
3
+ def self.instance
4
+ @instance ||= SchemaPrintspeak.new
5
+ end
6
+
7
+ attr_accessor :tables
8
+
9
+ def initialize
10
+ @tables = []
11
+ @current_table = nil
12
+ load_tables
13
+ end
14
+ private
15
+
16
+ def add_table(table)
17
+ @tables.push(table)
18
+ @current_table = table
19
+ end
20
+
21
+ def add_index(_table_name, columns, **opts)
22
+ @current_table[:indexes] = [] if @current_table[:indexes].nil?
23
+
24
+ @current_table[:indexes].push({columns: columns}.merge(opts))
25
+ end
26
+
27
+ # ----------------------------------------------------------------------
28
+ # Inject start
29
+ # original file: {{source_file}}
30
+ # ----------------------------------------------------------------------
31
+ def load_tables
32
+ {{rails_schema}}
33
+ end
34
+
35
+
36
+ def write_json(file)
37
+ schema[:meta][:rails] = @rails_version
38
+ File.write(file, JSON.pretty_generate(schema))
39
+ end
40
+
41
+ # This is the rails timestamp and will be replaced by the action rails version
42
+ def load(version:)
43
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
44
+ # puts 'about to load'
45
+ yield if block_given?
46
+
47
+ schema[:meta][:rails] = @rails_version
48
+
49
+ sort
50
+ # code to time
51
+
52
+ # log.kv 'extensions', schema[:db_info][:extensions].length
53
+ # log.kv 'tables', schema[:tables].length
54
+ # log.kv 'indexes', schema[:indexes].length
55
+ # # a low foreign_keys count is indicative of not using SQL referential integrity
56
+ # log.kv 'foreign_keys', schema[:foreign_keys].length
57
+ # log.kv 'Time Taken', (finish - start)
58
+
59
+ # puts schema[:db_info][:extensions]
60
+ # print_unique_keys(type: :foreign_keys, title: 'unique options for foreign_keys')
61
+ # print_unique_keys(type: :columns, title: 'unique options for columns')
62
+ # print_unique_keys(type: :fields, category: :integer , title: 'unique options for column - integer')
63
+ # print_unique_keys(type: :fields, category: :decimal , title: 'unique options for column - decimal')
64
+ # print_unique_keys(type: :fields, category: :string , title: 'unique options for column - string')
65
+ # print_unique_keys(type: :fields, category: :datetime, title: 'unique options for column - datetime')
66
+ # print_unique_keys(type: :fields, category: :date , title: 'unique options for column - date')
67
+ # print_unique_keys(type: :fields, category: :text , title: 'unique options for column - text')
68
+ # print_unique_keys(type: :fields, category: :boolean , title: 'unique options for column - boolean')
69
+ # print_unique_keys(type: :fields, category: :jsonb , title: 'unique options for column - jsonb')
70
+ # print_unique_keys(type: :fields, category: :hstore , title: 'unique options for column - hstore')
71
+ # print_unique_keys(type: :fields, category: :float , title: 'unique options for column - float')
72
+ end
73
+
74
+ def enable_extension(name)
75
+ # puts "enable_extension(#{name})"
76
+ schema[:meta][:db_info][:extensions] << name
77
+ end
78
+
79
+ def create_table(name, **opts)
80
+ id = opts[:id]
81
+ primary_key = opts[:primary_key] || (id == false ? nil : "id")
82
+ primary_key_type = if id == false
83
+ nil
84
+ elsif id.nil?
85
+ "bigint"
86
+ else
87
+ id
88
+ end
89
+
90
+ @current_table = {
91
+ name: name,
92
+ primary_key: primary_key, # infer the actual value that should be in the database
93
+ primary_key_type: primary_key_type, # infer the actual value that should be in the database
94
+ columns: [],
95
+ indexes: [],
96
+ rails_schema: { # as reported by the rails schema
97
+ primary_key: opts[:primary_key],
98
+ id: id,
99
+ force: opts[:force]
100
+ }
101
+ }
102
+ # schema[:tables][name] = @current_table
103
+ schema[:tables] << @current_table
104
+
105
+ yield(self) if block_given?
106
+ end
107
+
108
+ def add_field(name, type, **opts)
109
+ # puts "add_field(#{name}, #{type})"
110
+ row = { name: name, type: type, **opts }
111
+ @current_table[:columns] << row
112
+
113
+ add_unique_keys(row.keys, type: :columns)
114
+ add_unique_keys(row.keys, type: :fields, category: type)
115
+ end
116
+
117
+ def add_index(name, fields, **opts)
118
+ # puts "add_index(#{name})"
119
+ row = { name: name, fields: fields, **opts }
120
+ @current_table[:indexes] << row
121
+ schema[:indexes] << row
122
+ add_unique_keys(row.keys, type: :indexes)
123
+ end
124
+
125
+ # This method was introduced onto the schema in rails 5
126
+ def index(fields, **opts)
127
+ @rails_version = 5
128
+ name = opts[:name]
129
+ opts.delete(:name)
130
+ add_index(name, fields, **opts)
131
+ end
132
+
133
+ def create_view(name, **opts)
134
+ row = { name: name, **opts }
135
+ schema[:views] << row
136
+ add_unique_keys(row.keys, type: :views)
137
+ end
138
+
139
+ def add_foreign_key(left_table, right_table, **opts)
140
+ # puts "add_foreign_key(#{left_table}, #{right_table})"
141
+ row = { left: left_table, right: right_table, **opts }
142
+ schema[:foreign_keys] << row
143
+ add_unique_keys(row.keys, type: :foreign_keys)
144
+ end
145
+
146
+ def add_unique_keys(keys, type:, category: nil)
147
+ key = [type, category, keys.join('-')].compact.join('|')
148
+ return if @unique_keys.key?(key)
149
+
150
+ @unique_keys[key] = key
151
+ schema[:meta][:unique_keys] << { type: type, category: category, key: keys.join(','), keys: keys }
152
+ end
153
+
154
+ def print_unique_keys(type:, category: nil, title: )
155
+ log.section_heading(title)
156
+
157
+ filter_key_infos = schema[:meta][:unique_keys].select { |key_info| key_info[:type] == type && (category.nil? || key_info[:category] == category) }
158
+
159
+ # log.kv 'all', filter_key_infos.flat_map { |key_info| key_info[:keys] }.uniq, 50
160
+
161
+ filter_key_infos.each do |key_info|
162
+ log.kv key_info[:key], key_info[:keys], 50
163
+ end
164
+ end
165
+
166
+ def integer(name, **opts)
167
+ add_field(name, :integer, **opts)
168
+ end
169
+
170
+ def bigint(name, **opts)
171
+ add_field(name, :bigint, **opts)
172
+ end
173
+
174
+ def decimal(name, **opts)
175
+ add_field(name, :decimal, **opts)
176
+ end
177
+
178
+ def string(name, **opts)
179
+ add_field(name, :string, **opts)
180
+ end
181
+
182
+ def datetime(name, **opts)
183
+ add_field(name, :datetime, **opts)
184
+ end
185
+
186
+ def date(name, **opts)
187
+ add_field(name, :date, **opts)
188
+ end
189
+
190
+ def text(name, **opts)
191
+ add_field(name, :text, **opts)
192
+ end
193
+
194
+ def boolean(name, **opts)
195
+ add_field(name, :boolean, **opts)
196
+ end
197
+
198
+ def jsonb(name, **opts)
199
+ add_field(name, :jsonb, **opts)
200
+ end
201
+
202
+ def hstore(name, **opts)
203
+ add_field(name, :hstore, **opts)
204
+ end
205
+
206
+ def float(name, **opts)
207
+ add_field(name, :float, **opts)
208
+ end
209
+
210
+ def sort
211
+ schema[:indexes].sort_by! { |i| i[:name] }
212
+ schema[:tables].each { |table| table[:indexes].sort_by! { |i| i[:name] } }
213
+
214
+ # Insert a key that represents all unique keys, and then sort
215
+ unique_keys_per_group = schema[:meta][:unique_keys]
216
+ .group_by { |key_info| [key_info[:type], key_info[:category]] }
217
+ .map do |group, values|
218
+ all_keys = values.flat_map { |key_info| key_info[:keys] }.uniq
219
+ {
220
+ type: group[0],
221
+ category: group[01],
222
+ key: 'all',
223
+ keys: all_keys
224
+ }
225
+ end
226
+
227
+ schema[:meta][:unique_keys].concat(unique_keys_per_group)
228
+ schema[:meta][:unique_keys].sort! { |a,b| ([a[:type], a[:category],a[:key]] <=> [b[:type], b[:category],b[:key]]) }
229
+ end
230
+
231
+ end