k_domain 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee3ac6f9a2143cc6329183f38515615569399067e0919ba83eff7e5485a31b30
4
- data.tar.gz: c5e8016c595b30265436ae90acdcd28cbd2db9def4ea83308cf479840b04b173
3
+ metadata.gz: a69b94955a43f91d71e034b94a5caf0d3fdbb7b130c480d4eabc45818bbe2262
4
+ data.tar.gz: 0f4a126ee7c9bed5d99ac7449e5f97ec558030b126dbaa3c6194cdb5ce8430bd
5
5
  SHA512:
6
- metadata.gz: 1ccc3e4d22125ddebed3eb122d4dcd21392fcca079237ede44fb50b3ba351a780ebe894170e4e25bb08055d93f66ba7059127b4590e8c21f8956717fc5b78dec
7
- data.tar.gz: 7ab779bf4c936bc7465fa0667d24b5c459475a0d4e00a57cc9276310f3fb84ddd44683d1262f40e79b5de712609d0aefffab954b2d6d0f97a90251290dbe0cd6
6
+ metadata.gz: 3a7a877e80c9f23cdb93ab7952e027bdddc89bd6e888212c6fc0622cc0d5ae6d9b73e3e9651949ecd1afa2f1323e6446045f579cb6e83c030c5d8d711979deaa
7
+ data.tar.gz: 434275e01ec2308d4a1407f5e8bd7ab9ec9708218510b6a719c144e2d9b6abb7e2caafa67efc617ac33295cd276c2326ccd961468ee4870b38266ef1b1295296
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
 
data/STORIES.md ADDED
@@ -0,0 +1,44 @@
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 DO_SOMETHING, so that I QUALITY_OF_LIFE
12
+
13
+ - Subtask
14
+
15
+ ## Stories and tasks
16
+
17
+ ### Tasks - completed
18
+
19
+ Setup RubyGems and RubyDoc
20
+
21
+ - Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_domain)
22
+ - Attach documentation to [rubydoc.info](https://rubydoc.info/github/to-do-/k_domain/master)
23
+
24
+ Setup project management, requirement and SCRUM documents
25
+
26
+ - Setup readme file
27
+ - Setup user stories and tasks
28
+ - Setup a project backlog
29
+ - Setup an examples/usage document
30
+
31
+ Setup GitHub Action (test and lint)
32
+
33
+ - Setup Rspec action
34
+ - Setup RuboCop action
35
+
36
+ Setup new Ruby GEM
37
+
38
+ - Build out a standard GEM structure
39
+ - Add automated semantic versioning
40
+ - Add Rspec unit testing framework
41
+ - Add RuboCop linting
42
+ - Add Guard for automatic watch and test
43
+ - Add GitFlow support
44
+ - 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
+ ```
@@ -0,0 +1,226 @@
1
+ class LoadSchema
2
+ attr_reader :schema
3
+
4
+ def initialize
5
+ @unique_keys = {}
6
+ @current_table = nil
7
+ @rails_version = 4
8
+ @schema = {
9
+ tables: [],
10
+ foreign_keys: [],
11
+ indexes: [],
12
+ meta: {
13
+ rails: @rails_version,
14
+ database: {
15
+ type: 'postgres',
16
+ version: nil, # TODO
17
+ extensions: []
18
+ },
19
+ unique_keys: []
20
+ }
21
+ }
22
+ end
23
+
24
+ # ----------------------------------------------------------------------
25
+ # Inject start
26
+ # original file: {{source_file}}
27
+ # ----------------------------------------------------------------------
28
+ def load_schema
29
+ {{rails_schema}}
30
+ end
31
+
32
+ # ----------------------------------------------------------------------
33
+ # original file: {{source_file}}
34
+ # Inject end
35
+ # ----------------------------------------------------------------------
36
+
37
+ def write_json(file)
38
+ schema[:meta][:rails] = @rails_version
39
+ File.write(file, JSON.pretty_generate(schema))
40
+ end
41
+
42
+ # This is the rails timestamp and will be replaced by the action rails version
43
+ def load(version:)
44
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
45
+ # puts 'about to load'
46
+ yield if block_given?
47
+
48
+ schema[:meta][:rails] = @rails_version
49
+
50
+ sort
51
+ # code to time
52
+
53
+ # log.kv 'extensions', schema[:database][:extensions].length
54
+ # log.kv 'tables', schema[:tables].length
55
+ # log.kv 'indexes', schema[:indexes].length
56
+ # # a low foreign_keys count is indicative of not using SQL referential integrity
57
+ # log.kv 'foreign_keys', schema[:foreign_keys].length
58
+ # log.kv 'Time Taken', (finish - start)
59
+
60
+ # puts schema[:database][:extensions]
61
+ # print_unique_keys(type: :foreign_keys, title: 'unique options for foreign_keys')
62
+ # print_unique_keys(type: :columns, title: 'unique options for columns')
63
+ # print_unique_keys(type: :fields, category: :integer , title: 'unique options for column - integer')
64
+ # print_unique_keys(type: :fields, category: :decimal , title: 'unique options for column - decimal')
65
+ # print_unique_keys(type: :fields, category: :string , title: 'unique options for column - string')
66
+ # print_unique_keys(type: :fields, category: :datetime, title: 'unique options for column - datetime')
67
+ # print_unique_keys(type: :fields, category: :date , title: 'unique options for column - date')
68
+ # print_unique_keys(type: :fields, category: :text , title: 'unique options for column - text')
69
+ # print_unique_keys(type: :fields, category: :boolean , title: 'unique options for column - boolean')
70
+ # print_unique_keys(type: :fields, category: :jsonb , title: 'unique options for column - jsonb')
71
+ # print_unique_keys(type: :fields, category: :hstore , title: 'unique options for column - hstore')
72
+ # print_unique_keys(type: :fields, category: :float , title: 'unique options for column - float')
73
+ end
74
+
75
+ def enable_extension(name)
76
+ # puts "enable_extension(#{name})"
77
+ schema[:meta][:database][:extensions] << name
78
+ end
79
+
80
+ def create_table(name, **opts)
81
+ id = opts[:id]
82
+ primary_key = opts[:primary_key] || (id == false ? nil : "id")
83
+ primary_key_type = if id == false
84
+ nil
85
+ elsif id.nil?
86
+ "bigint"
87
+ else
88
+ id
89
+ end
90
+
91
+ @current_table = {
92
+ name: name,
93
+ primary_key: primary_key, # infer the actual value that should be in the database
94
+ primary_key_type: primary_key_type, # infer the actual value that should be in the database
95
+ columns: [],
96
+ indexes: [],
97
+ rails_schema: { # as reported by the rails schema
98
+ primary_key: opts[:primary_key],
99
+ id: id,
100
+ force: opts[:force]
101
+ }
102
+ }
103
+ # schema[:tables][name] = @current_table
104
+ schema[:tables] << @current_table
105
+
106
+ yield(self) if block_given?
107
+ end
108
+
109
+ def add_field(name, type, **opts)
110
+ # puts "add_field(#{name}, #{type})"
111
+ row = { name: name, type: type, **opts }
112
+ @current_table[:columns] << row
113
+
114
+ add_unique_keys(row.keys, type: :columns)
115
+ add_unique_keys(row.keys, type: :fields, category: type)
116
+ end
117
+
118
+ def add_index(name, fields, **opts)
119
+ # puts "add_index(#{name})"
120
+ row = { name: name, fields: fields, **opts }
121
+ @current_table[:indexes] << row
122
+ schema[:indexes] << row
123
+ add_unique_keys(row.keys, type: :indexes)
124
+ end
125
+
126
+ # This method was introduced onto the schema in rails 5
127
+ def index(fields, **opts)
128
+ @rails_version = 5
129
+ name = opts[:name]
130
+ opts.delete(:name)
131
+ add_index(name, fields, **opts)
132
+ end
133
+
134
+
135
+ def add_foreign_key(left_table, right_table, **opts)
136
+ # puts "add_foreign_key(#{left_table}, #{right_table})"
137
+ row = { left: left_table, right: right_table, **opts }
138
+ schema[:foreign_keys] << row
139
+ add_unique_keys(row.keys, type: :foreign_keys)
140
+ end
141
+
142
+ def add_unique_keys(keys, type:, category: nil)
143
+ key = [type, category, keys.join('-')].compact.join('|')
144
+ return if @unique_keys.key?(key)
145
+
146
+ @unique_keys[key] = key
147
+ schema[:meta][:unique_keys] << { type: type, category: category, key: keys.join(','), keys: keys }
148
+ end
149
+
150
+ def print_unique_keys(type:, category: nil, title: )
151
+ log.section_heading(title)
152
+
153
+ filter_key_infos = schema[:meta][:unique_keys].select { |key_info| key_info[:type] == type && (category.nil? || key_info[:category] == category) }
154
+
155
+ # log.kv 'all', filter_key_infos.flat_map { |key_info| key_info[:keys] }.uniq, 50
156
+
157
+ filter_key_infos.each do |key_info|
158
+ log.kv key_info[:key], key_info[:keys], 50
159
+ end
160
+ end
161
+
162
+ def integer(name, **opts)
163
+ add_field(name, :integer, **opts)
164
+ end
165
+
166
+ def bigint(name, **opts)
167
+ add_field(name, :bigint, **opts)
168
+ end
169
+
170
+ def decimal(name, **opts)
171
+ add_field(name, :decimal, **opts)
172
+ end
173
+
174
+ def string(name, **opts)
175
+ add_field(name, :string, **opts)
176
+ end
177
+
178
+ def datetime(name, **opts)
179
+ add_field(name, :datetime, **opts)
180
+ end
181
+
182
+ def date(name, **opts)
183
+ add_field(name, :date, **opts)
184
+ end
185
+
186
+ def text(name, **opts)
187
+ add_field(name, :text, **opts)
188
+ end
189
+
190
+ def boolean(name, **opts)
191
+ add_field(name, :boolean, **opts)
192
+ end
193
+
194
+ def jsonb(name, **opts)
195
+ add_field(name, :jsonb, **opts)
196
+ end
197
+
198
+ def hstore(name, **opts)
199
+ add_field(name, :hstore, **opts)
200
+ end
201
+
202
+ def float(name, **opts)
203
+ add_field(name, :float, **opts)
204
+ end
205
+
206
+ def sort
207
+ schema[:indexes].sort_by! { |i| i[:name] }
208
+ schema[:tables].each { |table| table[:indexes].sort_by! { |i| i[:name] } }
209
+
210
+ # Insert a key that represents all unique keys, and then sort
211
+ unique_keys_per_group = schema[:meta][:unique_keys]
212
+ .group_by { |key_info| [key_info[:type], key_info[:category]] }
213
+ .map do |group, values|
214
+ all_keys = values.flat_map { |key_info| key_info[:keys] }.uniq
215
+ {
216
+ type: group[0],
217
+ category: group[01],
218
+ key: 'all',
219
+ keys: all_keys
220
+ }
221
+ end
222
+
223
+ schema[:meta][:unique_keys].concat(unique_keys_per_group)
224
+ schema[:meta][:unique_keys].sort! { |a,b| ([a[:type], a[:category],a[:key]] <=> [b[:type], b[:category],b[:key]]) }
225
+ end
226
+ end
@@ -0,0 +1,67 @@
1
+ # Annotates the original schema with methods that implement existing method calls
2
+ # that are already in the schema so that we can build a hash.
3
+ #
4
+ # Writes a new annotated schema.rb file with a public method called load that
5
+ # builds the hash
6
+ # frozen_string_literal: true
7
+
8
+ module KDomain
9
+ module RawSchema
10
+ class Transform
11
+ include KLog::Logging
12
+
13
+ attr_reader :source_file
14
+ attr_reader :template_file
15
+ attr_reader :target_ruby_class
16
+
17
+ def initialize(source_file)#, target_file)
18
+ @source_file = source_file
19
+ @template_file = 'lib/k_domain/raw_schema/template.rb'
20
+ end
21
+
22
+ def call
23
+ # log.kv 'source_file', source_file
24
+ # log.kv 'template_file', template_file
25
+ # log.kv 'source_file?', File.exist?(source_file)
26
+ # log.kv 'template_file?', File.exist?(template_file)
27
+
28
+ log.error "Template not found: #{template_file}" unless File.exist?(template_file)
29
+
30
+ content = File.read(source_file)
31
+ content
32
+ .gsub!(/ActiveRecord::Schema.define/, 'load')
33
+
34
+ lines = content.lines.map { |line| " #{line}" }.join()
35
+
36
+ @target_ruby_class = File
37
+ .read(template_file)
38
+ .gsub('{{source_file}}', source_file)
39
+ .gsub('{{rails_schema}}', lines)
40
+ end
41
+
42
+ def write_target(target_file)
43
+ if target_ruby_class.nil?
44
+ puts '.call method has not been executed'
45
+ return
46
+ end
47
+
48
+ FileUtils.mkdir_p(File.dirname(target_file))
49
+ File.write(target_file, target_ruby_class)
50
+ end
51
+
52
+ def json
53
+ if target_ruby_class.nil?
54
+ puts '.call method has not been executed'
55
+ return
56
+ end
57
+
58
+ # load target_file
59
+ eval target_ruby_class
60
+
61
+ loader = LoadSchema.new
62
+ loader.load_schema()
63
+ loader.schema
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KDomain
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
5
5
  end
data/lib/k_domain.rb CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  require 'k_log'
4
4
  require 'k_domain/version'
5
-
6
-
5
+ require 'k_domain/raw_schema/transform'
7
6
 
8
7
  module KDomain
9
8
  # raise KDomain::Error, 'Sample message'
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.1
4
+ version: 0.0.2
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-09-25 00:00:00.000000000 Z
11
+ date: 2021-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: k_log
@@ -38,9 +38,12 @@ files:
38
38
  - ".rubocop.yml"
39
39
  - CODE_OF_CONDUCT.md
40
40
  - Gemfile
41
+ - Guardfile
41
42
  - LICENSE.txt
42
43
  - README.md
43
44
  - Rakefile
45
+ - STORIES.md
46
+ - USAGE.md
44
47
  - bin/console
45
48
  - bin/k
46
49
  - bin/kgitsync
@@ -50,6 +53,8 @@ files:
50
53
  - hooks/update-version
51
54
  - k_domain.gemspec
52
55
  - lib/k_domain.rb
56
+ - lib/k_domain/raw_schema/template.rb
57
+ - lib/k_domain/raw_schema/transform.rb
53
58
  - lib/k_domain/version.rb
54
59
  homepage: http://appydave.com/gems/k-domain
55
60
  licenses: