sequel-schema-dot-generator 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/README.md +13 -3
- data/lib/sequel_schema_dot_generator.rb +113 -0
- data/lib/{sequel/schema/dot/generator → sequel_schema_dot_generator}/diagram.dot.erb +0 -0
- data/lib/sequel_schema_dot_generator/schema_source_types/base.rb +23 -0
- data/lib/sequel_schema_dot_generator/schema_source_types/column.rb +34 -0
- data/lib/sequel_schema_dot_generator/schema_source_types/model.rb +30 -0
- data/lib/sequel_schema_dot_generator/version.rb +3 -0
- data/sequel-schema-dot-generator.gemspec +3 -3
- metadata +22 -37
- data/.rvmrc +0 -34
- data/lib/sequel/schema/dot/generator.rb +0 -118
- data/lib/sequel/schema/dot/generator/schema_source_types/base.rb +0 -29
- data/lib/sequel/schema/dot/generator/schema_source_types/column.rb +0 -40
- data/lib/sequel/schema/dot/generator/schema_source_types/model.rb +0 -36
- data/lib/sequel/schema/dot/generator/version.rb +0 -9
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2dc716c3f182abf30384a4b32318559291b40415
|
4
|
+
data.tar.gz: f6ddc030b24cc70467aec4957ae63b0362b5f729
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ec1c08f6477d03ae2852a0ee338064c5070c889a987ef563b79d94c24302965ec658ec564d4a6a502cd97ad0440ca7b112e11e0fd333922655b51270c20744e6
|
7
|
+
data.tar.gz: c42c2b2c1b32000e02ff740a1471e24d34735501cddd546a1945588026ced2522b80af54f0e468b9def1216d47461fa3ab0c77ade28e90601a35c8ef414ad12b
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
sequel-schema-dot-generator
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0.0-p247
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Sequel database structure Dot language generator
|
4
4
|
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/sequel-schema-dot-generator.png)](http://badge.fury.io/rb/sequel-schema-dot-generator)
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
@@ -27,8 +29,6 @@ Or install it yourself as:
|
|
27
29
|
|
28
30
|
puts dot_db.generate
|
29
31
|
|
30
|
-
=>
|
31
|
-
|
32
32
|
## Contributing
|
33
33
|
|
34
34
|
1. Fork it
|
@@ -39,7 +39,17 @@ Or install it yourself as:
|
|
39
39
|
|
40
40
|
## Changelog
|
41
41
|
|
42
|
+
### 0.0.4
|
43
|
+
- Module structure flattened
|
44
|
+
- Dir structure flattened
|
45
|
+
- active_support -> activesupport, smaller adjustments
|
46
|
+
- Transition to Ruby 2.0 and .ruby-version files for gem development
|
47
|
+
|
48
|
+
### 0.0.3
|
49
|
+
- Associations detection from model (`params[:schema_source_type] = :model`)
|
50
|
+
- New homepage
|
51
|
+
|
42
52
|
### 0.0.2
|
43
53
|
- optional colored association edges to distinguish them in big intersections (`params[:colored_associations]`)
|
44
54
|
- multiple foreign table support
|
45
|
-
- columns has written types in diagram
|
55
|
+
- columns has written types in diagram
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'sequel_schema_dot_generator/version'
|
2
|
+
require 'sequel_schema_dot_generator/schema_source_types/base'
|
3
|
+
require 'sequel_schema_dot_generator/schema_source_types/column'
|
4
|
+
require 'sequel_schema_dot_generator/schema_source_types/model'
|
5
|
+
require 'erb'
|
6
|
+
require 'logger'
|
7
|
+
require 'sequel'
|
8
|
+
require 'active_support/inflector'
|
9
|
+
|
10
|
+
# Module for generating Sequel schema structure into Dot language format
|
11
|
+
module SequelSchemaDotGenerator
|
12
|
+
class Generator
|
13
|
+
@db = nil
|
14
|
+
@dot_template_path = nil
|
15
|
+
@logger = nil
|
16
|
+
@colored_associations = nil
|
17
|
+
|
18
|
+
# @todo Consider write the params as block
|
19
|
+
#
|
20
|
+
# @param [Hash] params Setup of Generator instance
|
21
|
+
# :db [Sequel::Database] required From this one will be generated the diagram
|
22
|
+
# :logger [Logger] optional Will be used for logging
|
23
|
+
# :dot_template_path [String] optional Template is supposed to be ERB template. Will be used as template for resulting Dot file
|
24
|
+
# :colored_associations [Boolean] optional Whether lines representing associations will be draw in color (=False)
|
25
|
+
# :schema_source_type [Symbol] optional How will be data acquired (:column|:model)
|
26
|
+
#
|
27
|
+
def initialize params
|
28
|
+
check_params params
|
29
|
+
|
30
|
+
@db = params[:db]
|
31
|
+
@logger = params[:logger] || Logger.new(STDERR)
|
32
|
+
@dot_template_path = params[:dot_template_path] || File.join( File.dirname(__FILE__),
|
33
|
+
'sequel_schema_dot_generator/diagram.dot.erb')
|
34
|
+
@colored_associations = params[:colored_associations]
|
35
|
+
initialize_ss params[:schema_source_type]
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize_ss type
|
39
|
+
sst_params = @db, @db.tables
|
40
|
+
|
41
|
+
if type == :model
|
42
|
+
@schema_source = SchemaSourceType::Model.new *sst_params
|
43
|
+
end
|
44
|
+
|
45
|
+
# Column Source as fallback
|
46
|
+
@schema_source ||= SchemaSourceType::Column.new *sst_params
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [String] Content which can be passed to dot parsing tool
|
50
|
+
def generate
|
51
|
+
tables = []
|
52
|
+
|
53
|
+
@db.tables.each do |table_name|
|
54
|
+
next if table_name == :schema_info
|
55
|
+
tables << [table_name, @db.schema(table_name)]
|
56
|
+
end
|
57
|
+
|
58
|
+
relations = @schema_source.relations
|
59
|
+
|
60
|
+
if @colored_associations
|
61
|
+
edge_colors = random_color_set relations.count
|
62
|
+
else
|
63
|
+
edge_colors = Array.new relations.count, '000000'
|
64
|
+
end
|
65
|
+
|
66
|
+
ERB.new( File.read(@dot_template_path),nil,'>' ).result(binding)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# @param [Integer] number of colors we want to generate
|
72
|
+
#
|
73
|
+
# @return [Array] of random and unique colors
|
74
|
+
def random_color_set number
|
75
|
+
raise 'Number of colors must be greater than 0' if number < 1
|
76
|
+
colors = []
|
77
|
+
(1..number).each do
|
78
|
+
colors << random_unique_hex_color(colors)
|
79
|
+
end
|
80
|
+
|
81
|
+
colors
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
# @param [Array] existing colors which should be avoided
|
86
|
+
#
|
87
|
+
# @return [String] Random color which is not presented in existing param
|
88
|
+
def random_unique_hex_color existing
|
89
|
+
color = '%06x' % (rand * 0xffffff)
|
90
|
+
if existing.include?(color)
|
91
|
+
random_unique_hex_color existing
|
92
|
+
else
|
93
|
+
color
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Checks if all parameters for new Object are alright
|
98
|
+
def check_params params
|
99
|
+
unless params[:db].is_a?Sequel::Database
|
100
|
+
raise 'Database connection is supposed to be Sequel::Database. %s given'%params[:database_connection].class.name
|
101
|
+
end
|
102
|
+
unless params[:dot_template_path].nil? || params[:dot_template_path].is_a?(String) || File.exist?(params[:dot_template_path])
|
103
|
+
raise 'Template path is supposed to be string with an existing file. %s given'%params[:dot_template_path].inspect
|
104
|
+
end
|
105
|
+
unless params[:logger].nil? || params[:logger].is_a?(Logger)
|
106
|
+
raise 'Logger is supposed to be... Logger, know. %s given'%params[:logger].inspect
|
107
|
+
end
|
108
|
+
unless params[:colored_associations].nil? || !!params[:colored_associations] == params[:colored_associations]
|
109
|
+
raise 'Colored association is supposed to be boolean. %s given'%params[:colored_associations].inspect
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SequelSchemaDotGenerator
|
2
|
+
module SchemaSourceType
|
3
|
+
class Base
|
4
|
+
# Initialize Schema Source Type
|
5
|
+
#
|
6
|
+
# Tables could be retrieved from db connection, but there is plan to provide
|
7
|
+
# control over what tables will be in output structure
|
8
|
+
#
|
9
|
+
# @param [Sequel::Database] db for which should be acquired data
|
10
|
+
# @param [Array] tables for which should be acquired data
|
11
|
+
def initialize db, tables
|
12
|
+
@tables = tables
|
13
|
+
@db = db
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Array] associations for tables given to constructor
|
17
|
+
# Each item is array of [<foreign_table>, <id>, <table_name>, <foreign_column>]
|
18
|
+
def relations
|
19
|
+
raise NotImplementedError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module SequelSchemaDotGenerator
|
2
|
+
module SchemaSourceType
|
3
|
+
class Column < SchemaSourceType::Base
|
4
|
+
def relations
|
5
|
+
relations = []
|
6
|
+
|
7
|
+
@tables.each do |table_name|
|
8
|
+
@db[table_name].columns.select{|cn|cn=~/_id$/}.each do |column_name|
|
9
|
+
foreign_column = column_name.to_s
|
10
|
+
foreign_table = existing_table_name foreign_column.gsub(/_id$/, '')
|
11
|
+
relations << [foreign_table, 'id', table_name, foreign_column]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
relations
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# @param [String] name
|
21
|
+
#
|
22
|
+
# @return [String] form of name param in which it is name of existing table
|
23
|
+
def existing_table_name name
|
24
|
+
tables = @db.tables.map(&:to_s)
|
25
|
+
table_name = name if tables.include? name
|
26
|
+
table_name ||= name.pluralize if tables.include? name.pluralize
|
27
|
+
table_name ||= name.singularize if tables.include? name.singularize
|
28
|
+
table_name ||= 'association_table_not_found'
|
29
|
+
|
30
|
+
table_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SequelSchemaDotGenerator
|
2
|
+
module SchemaSourceType
|
3
|
+
class Model < SchemaSourceType::Base
|
4
|
+
def relations
|
5
|
+
relations = {}
|
6
|
+
|
7
|
+
@tables.collect do |table_name|
|
8
|
+
model = table_name.to_s.singularize.classify.constantize
|
9
|
+
model.associations.each do |assoc|
|
10
|
+
assoc_info = model.association_reflection(assoc)
|
11
|
+
|
12
|
+
right_key = assoc_info[:join_table].to_s+assoc_info[:right_key].to_s
|
13
|
+
left_key = assoc_info[:join_table].to_s+assoc_info[:left_key].to_s
|
14
|
+
|
15
|
+
if assoc_info[:type] == :many_to_many
|
16
|
+
relations[right_key] = [assoc_info[:join_table].to_s, assoc_info[:right_key], assoc_info[:class_name].constantize.implicit_table_name, assoc_info[:class_name].constantize.primary_key]
|
17
|
+
relations[left_key] = [assoc_info[:join_table].to_s, assoc_info[:left_key], assoc_info[:model].implicit_table_name, assoc_info[:model].primary_key]
|
18
|
+
else
|
19
|
+
# one_to_many
|
20
|
+
table_name = assoc_info[:model].implicit_table_name.to_s
|
21
|
+
table_key = assoc_info[:key].to_s
|
22
|
+
relations[right_key] = [table_name, table_key, assoc_info[:class_name].constantize.implicit_table_name, assoc_info[:class_name].constantize.primary_key]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
relations.values
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require File.expand_path 'lib/
|
4
|
+
require File.expand_path 'lib/sequel_schema_dot_generator/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'sequel-schema-dot-generator'
|
8
|
-
spec.version =
|
8
|
+
spec.version = SequelSchemaDotGenerator::VERSION
|
9
9
|
spec.authors = ['Mailo Svetel']
|
10
10
|
spec.email = %w(development@rooland.cz)
|
11
11
|
spec.description = %q{This gem makes it easier to generate database schema overview image}
|
@@ -22,5 +22,5 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency 'rake'
|
23
23
|
|
24
24
|
spec.add_dependency 'sequel'
|
25
|
-
spec.add_dependency '
|
25
|
+
spec.add_dependency 'activesupport'
|
26
26
|
end
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel-schema-dot-generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.4
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Mailo Svetel
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-11-02 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,49 +27,43 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: sequel
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
56
|
+
name: activesupport
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
description: This gem makes it easier to generate database schema overview image
|
@@ -83,47 +74,41 @@ extensions: []
|
|
83
74
|
extra_rdoc_files: []
|
84
75
|
files:
|
85
76
|
- .gitignore
|
86
|
-
- .
|
77
|
+
- .ruby-gemset
|
78
|
+
- .ruby-version
|
87
79
|
- Gemfile
|
88
80
|
- LICENSE.txt
|
89
81
|
- README.md
|
90
82
|
- Rakefile
|
91
|
-
- lib/
|
92
|
-
- lib/
|
93
|
-
- lib/
|
94
|
-
- lib/
|
95
|
-
- lib/
|
96
|
-
- lib/
|
83
|
+
- lib/sequel_schema_dot_generator.rb
|
84
|
+
- lib/sequel_schema_dot_generator/diagram.dot.erb
|
85
|
+
- lib/sequel_schema_dot_generator/schema_source_types/base.rb
|
86
|
+
- lib/sequel_schema_dot_generator/schema_source_types/column.rb
|
87
|
+
- lib/sequel_schema_dot_generator/schema_source_types/model.rb
|
88
|
+
- lib/sequel_schema_dot_generator/version.rb
|
97
89
|
- sequel-schema-dot-generator.gemspec
|
98
90
|
homepage: http://www.rooland.cz/sequel-schema-dot-generator-gem
|
99
91
|
licenses:
|
100
92
|
- MIT
|
93
|
+
metadata: {}
|
101
94
|
post_install_message:
|
102
95
|
rdoc_options: []
|
103
96
|
require_paths:
|
104
97
|
- lib
|
105
98
|
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
99
|
requirements:
|
108
|
-
- -
|
100
|
+
- - '>='
|
109
101
|
- !ruby/object:Gem::Version
|
110
102
|
version: '0'
|
111
|
-
segments:
|
112
|
-
- 0
|
113
|
-
hash: -3800259323698899955
|
114
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
104
|
requirements:
|
117
|
-
- -
|
105
|
+
- - '>='
|
118
106
|
- !ruby/object:Gem::Version
|
119
107
|
version: '0'
|
120
|
-
segments:
|
121
|
-
- 0
|
122
|
-
hash: -3800259323698899955
|
123
108
|
requirements: []
|
124
109
|
rubyforge_project:
|
125
|
-
rubygems_version: 1.
|
110
|
+
rubygems_version: 2.1.2
|
126
111
|
signing_key:
|
127
|
-
specification_version:
|
112
|
+
specification_version: 4
|
128
113
|
summary: Dot language format generator for Sequel schema structure
|
129
114
|
test_files: []
|
data/.rvmrc
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
-
# development environment upon cd'ing into the directory
|
5
|
-
|
6
|
-
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
7
|
-
# Only full ruby name is supported here, for short names use:
|
8
|
-
# echo "rvm use 1.9.3" > .rvmrc
|
9
|
-
environment_id="ruby-1.9.3-p385@sequel-dot-generator"
|
10
|
-
|
11
|
-
# Uncomment the following lines if you want to verify rvm version per project
|
12
|
-
# rvmrc_rvm_version="1.18.8 (stable)" # 1.10.1 seams as a safe start
|
13
|
-
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
14
|
-
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
15
|
-
# return 1
|
16
|
-
# }
|
17
|
-
|
18
|
-
# First we attempt to load the desired environment directly from the environment
|
19
|
-
# file. This is very fast and efficient compared to running through the entire
|
20
|
-
# CLI and selector. If you want feedback on which environment was used then
|
21
|
-
# insert the word 'use' after --create as this triggers verbose mode.
|
22
|
-
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
23
|
-
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
24
|
-
then
|
25
|
-
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
26
|
-
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
27
|
-
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
28
|
-
else
|
29
|
-
# If the environment file has not yet been created, use the RVM CLI to select.
|
30
|
-
rvm --create "$environment_id" || {
|
31
|
-
echo "Failed to create RVM environment '${environment_id}'."
|
32
|
-
return 1
|
33
|
-
}
|
34
|
-
fi
|
@@ -1,118 +0,0 @@
|
|
1
|
-
require 'sequel/schema/dot/generator/version'
|
2
|
-
require 'sequel/schema/dot/generator/schema_source_types/base'
|
3
|
-
require 'sequel/schema/dot/generator/schema_source_types/column'
|
4
|
-
require 'sequel/schema/dot/generator/schema_source_types/model'
|
5
|
-
require 'erb'
|
6
|
-
require 'logger'
|
7
|
-
require 'sequel'
|
8
|
-
require 'active_support/inflector'
|
9
|
-
|
10
|
-
module Sequel
|
11
|
-
module Schema
|
12
|
-
module Dot
|
13
|
-
# Module for generating Sequel schema structure into Dot language format
|
14
|
-
module Generator
|
15
|
-
class Generator
|
16
|
-
@db = nil
|
17
|
-
@dot_template_path = nil
|
18
|
-
@logger = nil
|
19
|
-
@colored_associations = nil
|
20
|
-
|
21
|
-
# @todo Consider write the params as block
|
22
|
-
#
|
23
|
-
# @param [Hash] params Setup of Generator instance
|
24
|
-
# :db [Sequel::Database] required From this one will be generated the diagram
|
25
|
-
# :logger [Logger] optional Will be used for logging
|
26
|
-
# :dot_template_path [String] optional Template is supposed to be ERB template. Will be used as template for resulting Dot file
|
27
|
-
# :colored_associations [Boolean] optional Whether lines representing associations will be draw in color (=False)
|
28
|
-
# :schema_source_type [Symbol] optional How will be data acquired (:column|:model)
|
29
|
-
#
|
30
|
-
def initialize params
|
31
|
-
check_params params
|
32
|
-
|
33
|
-
@db = params[:db]
|
34
|
-
@logger = params[:logger] || Logger.new(STDERR)
|
35
|
-
@dot_template_path = params[:dot_template_path] || File.join(File.dirname(__FILE__), 'generator/diagram.dot.erb')
|
36
|
-
@colored_associations = params[:colored_associations]
|
37
|
-
initialize_ss params[:schema_source_type]
|
38
|
-
end
|
39
|
-
|
40
|
-
def initialize_ss type
|
41
|
-
sst_params = @db, @db.tables
|
42
|
-
|
43
|
-
if type == :model
|
44
|
-
@schema_source = SchemaSourceType::Model.new *sst_params
|
45
|
-
end
|
46
|
-
|
47
|
-
# Column Source as fallback
|
48
|
-
@schema_source ||= SchemaSourceType::Column.new *sst_params
|
49
|
-
end
|
50
|
-
|
51
|
-
# @return [String] Content which can be passed to dot parsing tool
|
52
|
-
def generate
|
53
|
-
tables = []
|
54
|
-
|
55
|
-
@db.tables.each do |table_name|
|
56
|
-
next if table_name == :schema_info
|
57
|
-
tables << [table_name, @db.schema(table_name)]
|
58
|
-
end
|
59
|
-
|
60
|
-
relations = @schema_source.relations
|
61
|
-
|
62
|
-
if @colored_associations
|
63
|
-
edge_colors = random_color_set relations.count
|
64
|
-
else
|
65
|
-
edge_colors = Array.new relations.count, '000000'
|
66
|
-
end
|
67
|
-
|
68
|
-
ERB.new( File.read(@dot_template_path),nil,'>' ).result(binding)
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
# @param [Integer] number of colors we want to generate
|
74
|
-
#
|
75
|
-
# @return [Array] of random and unique colors
|
76
|
-
def random_color_set number
|
77
|
-
raise 'Number of colors must be greater than 0' if number < 1
|
78
|
-
colors = []
|
79
|
-
(1..number).each do
|
80
|
-
colors << random_unique_hex_color(colors)
|
81
|
-
end
|
82
|
-
|
83
|
-
colors
|
84
|
-
end
|
85
|
-
|
86
|
-
|
87
|
-
# @param [Array] existing colors which should be avoided
|
88
|
-
#
|
89
|
-
# @return [String] Random color which is not presented in existing param
|
90
|
-
def random_unique_hex_color existing
|
91
|
-
color = '%06x' % (rand * 0xffffff)
|
92
|
-
if existing.include?(color)
|
93
|
-
random_unique_hex_color existing
|
94
|
-
else
|
95
|
-
color
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Checks if all parameters for new Object are alright
|
100
|
-
def check_params params
|
101
|
-
unless params[:db].is_a?Sequel::Database
|
102
|
-
raise 'Database connection is supposed to be Sequel::Database. %s given'%params[:database_connection].class.name
|
103
|
-
end
|
104
|
-
unless params[:dot_template_path].nil? || params[:dot_template_path].is_a?(String) || File.exist?(params[:dot_template_path])
|
105
|
-
raise 'Template path is supposed to be string with an existing file. %s given'%params[:dot_template_path].inspect
|
106
|
-
end
|
107
|
-
unless params[:logger].nil? || params[:logger].is_a?(Logger)
|
108
|
-
raise 'Logger is supposed to be... Logger, know. %s given'%params[:logger].inspect
|
109
|
-
end
|
110
|
-
unless params[:colored_associations].nil? || !!params[:colored_associations] == params[:colored_associations]
|
111
|
-
raise 'Colored association is supposed to be boolean. %s given'%params[:colored_associations].inspect
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
module Schema
|
3
|
-
module Dot
|
4
|
-
module Generator
|
5
|
-
module SchemaSourceType
|
6
|
-
class Base
|
7
|
-
# Initialize Schema Source Type
|
8
|
-
#
|
9
|
-
# Tables could be retrieved from db connection, but there is plan to provide
|
10
|
-
# control over what tables will be in output structure
|
11
|
-
#
|
12
|
-
# @param [Sequel::Database] db for which should be acquired data
|
13
|
-
# @param [Array] tables for which should be acquired data
|
14
|
-
def initialize db, tables
|
15
|
-
@tables = tables
|
16
|
-
@db = db
|
17
|
-
end
|
18
|
-
|
19
|
-
# @return [Array] associations for tables given to constructor
|
20
|
-
# Each item is array of [<foreign_table>, <id>, <table_name>, <foreign_column>]
|
21
|
-
def relations
|
22
|
-
raise NotImplementedError
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
module Schema
|
3
|
-
module Dot
|
4
|
-
module Generator
|
5
|
-
module SchemaSourceType
|
6
|
-
class Column < SchemaSourceType::Base
|
7
|
-
def relations
|
8
|
-
relations = []
|
9
|
-
|
10
|
-
@tables.each do |table_name|
|
11
|
-
@db[table_name].columns.select{|cn|cn=~/_id$/}.each do |column_name|
|
12
|
-
foreign_column = column_name.to_s
|
13
|
-
foreign_table = existing_table_name foreign_column.gsub(/_id$/, '')
|
14
|
-
relations << [foreign_table, 'id', table_name, foreign_column]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
relations
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
# @param [String] name
|
24
|
-
#
|
25
|
-
# @return [String] form of name param in which it is name of existing table
|
26
|
-
def existing_table_name name
|
27
|
-
tables = @db.tables.map(&:to_s)
|
28
|
-
table_name = name if tables.include? name
|
29
|
-
table_name ||= name.pluralize if tables.include? name.pluralize
|
30
|
-
table_name ||= name.singularize if tables.include? name.singularize
|
31
|
-
table_name ||= 'association_table_not_found'
|
32
|
-
|
33
|
-
table_name
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
module Schema
|
3
|
-
module Dot
|
4
|
-
module Generator
|
5
|
-
module SchemaSourceType
|
6
|
-
class Model < SchemaSourceType::Base
|
7
|
-
def relations
|
8
|
-
relations = {}
|
9
|
-
|
10
|
-
@tables.collect do |table_name|
|
11
|
-
model = table_name.to_s.singularize.classify.constantize
|
12
|
-
model.associations.each do |assoc|
|
13
|
-
assoc_info = model.association_reflection(assoc)
|
14
|
-
|
15
|
-
right_key = assoc_info[:join_table].to_s+assoc_info[:right_key].to_s
|
16
|
-
left_key = assoc_info[:join_table].to_s+assoc_info[:left_key].to_s
|
17
|
-
|
18
|
-
if assoc_info[:type] == :many_to_many
|
19
|
-
relations[right_key] = [assoc_info[:join_table].to_s, assoc_info[:right_key], assoc_info[:class_name].constantize.implicit_table_name, assoc_info[:class_name].constantize.primary_key]
|
20
|
-
relations[left_key] = [assoc_info[:join_table].to_s, assoc_info[:left_key], assoc_info[:model].implicit_table_name, assoc_info[:model].primary_key]
|
21
|
-
else
|
22
|
-
# one_to_many
|
23
|
-
table_name = assoc_info[:model].implicit_table_name.to_s
|
24
|
-
table_key = assoc_info[:key].to_s
|
25
|
-
relations[right_key] = [table_name, table_key, assoc_info[:class_name].constantize.implicit_table_name, assoc_info[:class_name].constantize.primary_key]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
relations.values
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|