dynamic-active-model 0.1.0 → 0.2.0
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67d4e71c097cafd08ed7e9c3ed2ffd4d8b22b5787fd2f6ab498a709b75de5215
|
4
|
+
data.tar.gz: a5cad0b2293d861f93bdf9d6c8fbc983ca9c4af1ab9bb60c22216c074e2b01c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5939469d103fb9c6a6d71ea987e6b0f8fe9c117d1014ca5d752c25307c1d5ff586d64cebae3571cc1eb276e9cfd760e577bae2066c9812223055c1f309b0cb50
|
7
|
+
data.tar.gz: 422a33565554689d2055122cc45234e7fd4c7f1f766f018b4fd080df6c86051cc79d950fec706702f489bd225793e84b3dc1d4cc7b66ae2dd2667fe507e0f5f1
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'dynamic-active-model'
|
5
|
+
require 'optparse'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
DEFAULT_CONFIG_FILE = "#{ENV['HOME']}/.dynamic-db-explorer.yml"
|
9
|
+
|
10
|
+
options = {
|
11
|
+
base_module: Object,
|
12
|
+
connection_options: {},
|
13
|
+
skip_tables: [],
|
14
|
+
relationships: {},
|
15
|
+
config_file: nil,
|
16
|
+
config_section: nil,
|
17
|
+
class_files_dir: nil
|
18
|
+
}
|
19
|
+
|
20
|
+
# rubocop:disable Metrics/BlockLength
|
21
|
+
OptionParser.new do |opts|
|
22
|
+
opts.banner = 'Usage: dynamic-db-explorer'
|
23
|
+
|
24
|
+
opts.on('-h', '--help', 'Prints this help') do
|
25
|
+
puts opts
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on('--username USERMNAME', 'DB username') do |v|
|
30
|
+
options[:connection_options][:username] = v
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on('--host HOST', 'DB host') do |v|
|
34
|
+
options[:connection_options][:host] = v
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on('--port PORT', 'DB port') do |v|
|
38
|
+
options[:connection_options][:port] = v
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on('--password PASSWORD', 'DB password') do |v|
|
42
|
+
options[:connection_options][:password] = v
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on('--adapter ADAPTER', 'DB adapter') do |v|
|
46
|
+
options[:connection_options][:adapter] = v
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on('--database DATABASE', 'DB name') do |v|
|
50
|
+
options[:connection_options][:database] = v
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on('--module MODULE_NAME', 'module name') do |v|
|
54
|
+
Object.const_set(v, Module.new)
|
55
|
+
options[:base_module] = Object.const_get(v)
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on('-c', '--config FILE', "config file, default #{DEFAULT_CONFIG_FILE}") do |v|
|
59
|
+
options[:config_file] = v
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on('-s', '--section SECTION', 'config file section') do |v|
|
63
|
+
options[:config_file] = DEFAULT_CONFIG_FILE if !options[:config_file] && File.exist?(DEFAULT_CONFIG_FILE)
|
64
|
+
options[:config_section] = v
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on('--create-class-files DIR', 'Create ActiveRecord class files') do |v|
|
68
|
+
raise("#{v} not found") unless File.exist?(v)
|
69
|
+
|
70
|
+
options[:class_files_dir] = v
|
71
|
+
end
|
72
|
+
end.parse!
|
73
|
+
# rubocop:enable Metrics/BlockLength
|
74
|
+
|
75
|
+
if options[:config_file]
|
76
|
+
raise('must specify a section') unless options[:config_section]
|
77
|
+
|
78
|
+
config = YAML.load_file(options[:config_file])[options[:config_section]]
|
79
|
+
options[:skip_tables] = config.delete('skip_tables') || []
|
80
|
+
options[:relationships] = config.delete('relationships') || {}
|
81
|
+
if (module_name = config.delete('module'))
|
82
|
+
Object.const_set(module_name, Module.new)
|
83
|
+
options[:base_module] = Object.const_get(module_name)
|
84
|
+
end
|
85
|
+
options[:connection_options] = config.each_with_object({}) { |(name, value), hsh| hsh[name.to_sym] = value }
|
86
|
+
end
|
87
|
+
|
88
|
+
database = DynamicActiveModel::Explorer.explore(
|
89
|
+
options[:base_module],
|
90
|
+
options[:connection_options],
|
91
|
+
options[:skip_tables],
|
92
|
+
options[:relationships]
|
93
|
+
)
|
94
|
+
|
95
|
+
if options[:class_files_dir]
|
96
|
+
database.models.each do |model|
|
97
|
+
DynamicActiveModel::TemplateClassFile.new(model).create_template!(options[:class_files_dir])
|
98
|
+
end
|
99
|
+
else
|
100
|
+
require 'irb'
|
101
|
+
IRB.start(__FILE__)
|
102
|
+
end
|
data/lib/dynamic-active-model.rb
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
# DynamicActiveModel module for create ActiveRecord models
|
4
4
|
module DynamicActiveModel
|
5
5
|
autoload :Database, 'dynamic-active-model/database'
|
6
|
+
autoload :Explorer, 'dynamic-active-model/explorer'
|
6
7
|
autoload :Factory, 'dynamic-active-model/factory'
|
7
8
|
autoload :ForeignKey, 'dynamic-active-model/foreign_key'
|
8
9
|
autoload :Relations, 'dynamic-active-model/relations'
|
10
|
+
autoload :TemplateClassFile, 'dynamic-active-model/template_class_file'
|
9
11
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicActiveModel
|
4
|
+
# DynamicActiveModel::EWplorer creates models and relationships
|
5
|
+
module Explorer
|
6
|
+
def self.explore(base_module, connection_options, skip_tables = [], relationships = {})
|
7
|
+
database = create_models!(base_module, connection_options, skip_tables)
|
8
|
+
build_relationships!(database, relationships)
|
9
|
+
database
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create_models!(base_module, connection_options, skip_tables)
|
13
|
+
database = Database.new(base_module, connection_options)
|
14
|
+
skip_tables.each do |table_name|
|
15
|
+
table_name = Regexp.new("^#{table_name}") if table_name.include?('*')
|
16
|
+
database.skip_table(table_name)
|
17
|
+
end
|
18
|
+
database.create_models!
|
19
|
+
database
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.build_relationships!(database, relationships)
|
23
|
+
relations = Relations.new(database)
|
24
|
+
relationships.each do |table_name, foreign_keys|
|
25
|
+
foreign_keys.each do |foreign_key, relationship_name|
|
26
|
+
relations.add_foreign_key(table_name, foreign_key, relationship_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
relations.build!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicActiveModel
|
4
|
+
# DynamicActiveModel::TemplateClassFile creates ActiveRecord file for model
|
5
|
+
class TemplateClassFile
|
6
|
+
def initialize(model)
|
7
|
+
@model = model
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_template!(dir)
|
11
|
+
file = dir + '/' + @model.name.underscore + '.rb'
|
12
|
+
File.open(file, 'wb') { |f| f.write(to_s) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
str = "class #{@model.name} < ActiveRecord::Base\n".dup
|
17
|
+
str << " self.table_name = #{@model.table_name.to_sym.inspect}\n" unless @model.name.underscore.pluralize == @model.table_name
|
18
|
+
all_has_many_relationships.each do |assoc|
|
19
|
+
append_association!(str, assoc)
|
20
|
+
end
|
21
|
+
all_belongs_to_relationships.each do |assoc|
|
22
|
+
append_association!(str, assoc)
|
23
|
+
end
|
24
|
+
str << "end\n"
|
25
|
+
str
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def all_has_many_relationships
|
31
|
+
@model.reflect_on_all_associations.select do |assoc|
|
32
|
+
assoc.is_a?(ActiveRecord::Reflection::HasManyReflection)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def all_belongs_to_relationships
|
37
|
+
@model.reflect_on_all_associations.select do |assoc|
|
38
|
+
assoc.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def append_association!(str, assoc)
|
43
|
+
assoc_type = assoc.is_a?(ActiveRecord::Reflection::HasManyReflection) ? 'has_many' : 'belongs_to'
|
44
|
+
association_options = assoc_type == 'has_many' ? has_many_association_options(assoc) : belongs_to_association_options(assoc)
|
45
|
+
str << " #{assoc_type} #{assoc.name.inspect}"
|
46
|
+
unless association_options.empty?
|
47
|
+
association_options.each do |name, value|
|
48
|
+
str << ", #{name}: '#{value}'"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
str << "\n"
|
52
|
+
end
|
53
|
+
|
54
|
+
def has_many_association_options(assoc)
|
55
|
+
options = {}
|
56
|
+
options[:class_name] = assoc.options[:class_name] unless assoc.options[:class_name].underscore.pluralize == assoc.name.to_s
|
57
|
+
options[:foreign_key] = assoc.options[:foreign_key] unless assoc.options[:foreign_key] == default_foreign_key_name
|
58
|
+
options[:primary_key] = assoc.options[:primary_key] unless assoc.options[:primary_key] == 'id'
|
59
|
+
options
|
60
|
+
end
|
61
|
+
|
62
|
+
def belongs_to_association_options(assoc)
|
63
|
+
options = {}
|
64
|
+
options[:class_name] = assoc.options[:class_name] unless assoc.options[:class_name] == assoc.name.to_s.classify
|
65
|
+
options[:foreign_key] = assoc.options[:foreign_key] unless assoc.options[:foreign_key] == (assoc.options[:class_name].underscore + '_id')
|
66
|
+
options[:primary_key] = assoc.options[:primary_key] unless assoc.options[:primary_key] == 'id'
|
67
|
+
options
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_foreign_key_name
|
71
|
+
@model.table_name.underscore.singularize + '_id'
|
72
|
+
end
|
73
|
+
|
74
|
+
def const_get(class_name)
|
75
|
+
class_name.split('::').inject(Object) { |mod, name| mod.const_get(name) }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic-active-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Doug Youch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -26,15 +26,19 @@ dependencies:
|
|
26
26
|
version: '0'
|
27
27
|
description: Dynamically create ActiveRecord models for tables
|
28
28
|
email: dougyouch@gmail.com
|
29
|
-
executables:
|
29
|
+
executables:
|
30
|
+
- dynamic-db-explorer
|
30
31
|
extensions: []
|
31
32
|
extra_rdoc_files: []
|
32
33
|
files:
|
34
|
+
- bin/dynamic-db-explorer
|
33
35
|
- lib/dynamic-active-model.rb
|
34
36
|
- lib/dynamic-active-model/database.rb
|
37
|
+
- lib/dynamic-active-model/explorer.rb
|
35
38
|
- lib/dynamic-active-model/factory.rb
|
36
39
|
- lib/dynamic-active-model/foreign_key.rb
|
37
40
|
- lib/dynamic-active-model/relations.rb
|
41
|
+
- lib/dynamic-active-model/template_class_file.rb
|
38
42
|
homepage: https://github.com/dougyouch/dynamic-active-model
|
39
43
|
licenses: []
|
40
44
|
metadata: {}
|