erdb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 25ee47da83fb1accfed1d03d3c4fa6b0639640961180bfe86985a9f272bac629
4
+ data.tar.gz: 345bc5e3caf6f76a70dbc7af2c237770c9e7938e5bd39eddfeb34d5f14cba870
5
+ SHA512:
6
+ metadata.gz: 6da4c1fc2b88e3507e6e364edc27f6bb9abe7d6a3d01002224294cb2c7c302edd594cbeea0efa5d06fdb7ab7516f1c0ac0b34db9084acf488b718b26429a8970
7
+ data.tar.gz: 72beed6a8e53f9e1bd19360f1796980797bdfb35e5df889294602df85105cb3d5fe9773abeed0fabdcac20e69ce1f74f1709f7f3c1ff5efe5fbd6519a5c12aec
data/CHANGES.md ADDED
@@ -0,0 +1,6 @@
1
+ ### 1.0.0
2
+
3
+ - Initial release
4
+ - Added ERD generation for SQLite, PostgreSQL and MySQL
5
+ - Use [Azimutt](https://azimutt.app) to generate the diagrams
6
+ - Use [DBDiagram](https://dbdiagram.io) to generate the diagrams
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # ERDB [![Gem Version](https://badge.fury.io/rb/erdb.svg)](https://badge.fury.io/rb/erdb) [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop)
2
+
3
+ ERDB is a Ruby Gem for generation Entity-Relationship Diagrams (ERD).
4
+ Currently it support `sqlite3`, `mysql2` and `postgresql` database.
5
+ ERDB is just a wrapper to automate the process of generating ERD using -
6
+
7
+ - [Azimutt(Open Source)](https://azimutt.app)
8
+ - [DBDiagram](https://dbdiagram.io)
9
+
10
+ > Currently there is no support for `one-to-one` relationship. If you want to use it you have to manually edit the generated ERD.
11
+
12
+ <!-- graphviz coming soon -->
13
+
14
+ ## Demo
15
+
16
+ ![erdb](./images/erdb.gif)
17
+
18
+ ## Requirements
19
+
20
+ - Ruby 2.7.0 or higher
21
+ - Chrome Browser.
22
+
23
+ ## Installation
24
+
25
+ Use the package manager [gem](https://rubygems.org/) to install ERDB.
26
+
27
+ ```bash
28
+ gem install erdb
29
+ ```
30
+
31
+ > Important note for Linux users: The clipboard requires the _xsel_ or the _xclip_ command-line program. On debian and ubuntu, _xsel_ can be installed with: `sudo apt-get install xsel`
32
+ > Visit [clipboard](https://github.com/janlelis/clipboard) for more details.
33
+
34
+ #### Adapters
35
+
36
+ For `mysql2` and `postgresql` database, you have to install the required gem.
37
+ I didn't include them in the gemspec because I don't want to install them if you don't need them.
38
+ Because it depends on native extensions, you'll need a compiler and the development headers for your Ruby and database.
39
+
40
+ ```bash
41
+ gem install mysql2
42
+ gem install pg
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ After install ERDB, you can use `erdb` command to generate ER Diagram.
48
+
49
+ ```bash
50
+ erdb
51
+ ```
52
+
53
+ ## Why I created this gem?
54
+
55
+ I know there are many tools available for generating ERD,
56
+ but I wanted to create a tool that is easy to use and can be used with any database.
57
+ `Azimutt` also support converting schema to ERD, but it's only working well with remote databases.
58
+ If I want to generate local database using `Azimutt`, I have to setup `Azimutt` locally that is alot of step -\_-
59
+
60
+ ## Roadmap
61
+
62
+ - [x] Support `sqlite3`, `mysql2` and `postgresql` database.
63
+ - [x] Generate ERD using Azimutt
64
+ - [x] Generate ERD using DBDiagram
65
+ - [ ] Support `MongoDB` database.
66
+ - [ ] Generate ERD using Graphviz
67
+
68
+ ## Contributing
69
+
70
+ Pull requests are welcome. Feel free to open an issue first to discuss what you would like to change.
71
+
72
+ ## License
73
+
74
+ This project is licensed under [MIT](https://choosealicense.com/licenses/mit/) license.
75
+ View [LICENSE](./LICENSE) for more details.
data/bin/erdb ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/erdb"
4
+
5
+ ERDB::Cli.start(ARGV)
@@ -0,0 +1,60 @@
1
+ module ERDB
2
+ class Db
3
+ #
4
+ # @param adapter [String] The adapter to use.
5
+ # @param database [String] The database to connect to.
6
+ # @return [void]
7
+ #
8
+ def initialize(adapter, database)
9
+ @adapter = adapter
10
+ @database = database
11
+ end
12
+
13
+ #
14
+ # Connect to a database.
15
+ #
16
+ def connect
17
+ raise "[connect] Not implemented."
18
+ end
19
+
20
+ #
21
+ # Disconnect from a database.
22
+ #
23
+ def disconnect
24
+ raise "[disconnect] Not implemented."
25
+ end
26
+
27
+ #
28
+ # Convert database tables to ERD convertable Array.
29
+ # @return [Array] The converted hash format. see example result below.
30
+ #
31
+ # @example Example result:
32
+ # ```ruby
33
+ # [
34
+ # {
35
+ # name: "table_name",
36
+ # is_join_table: false,
37
+ # columns: [{ name: "column_name", type: "column_type" }, ...],
38
+ # relations: [
39
+ # {
40
+ # from: {
41
+ # table: "table_name",
42
+ # column: "column_name"
43
+ # },
44
+ # to: {
45
+ # table: "table_name",
46
+ # column: "column_name"
47
+ # }
48
+ # }
49
+ # ...
50
+ # ]
51
+ # }
52
+ # ...
53
+ # ]
54
+ # ```
55
+ #
56
+ def to_erdb
57
+ raise "[to_erdb] Not implemented."
58
+ end
59
+ end
60
+ end
@@ -0,0 +1 @@
1
+ # Planning to use this file to create a NoSQL database for the project
@@ -0,0 +1,114 @@
1
+ require "active_record"
2
+ require_relative "db"
3
+
4
+ module ERDB
5
+ class SQL < Db
6
+ #
7
+ # Initialize a new SQL instance.
8
+ #
9
+ def initialize(adapter, database)
10
+ super
11
+
12
+ @db = ActiveRecord::Base
13
+ @connection = nil
14
+ end
15
+
16
+ #
17
+ # Connect to a database.
18
+ #
19
+ def connect
20
+ puts "\n"
21
+ puts "Connecting to #{@adapter} database..."
22
+
23
+ case @adapter.to_sym
24
+ when :sqlite3
25
+ connect_sqlite3
26
+ when :postgresql, :mysql2
27
+ connect_with_connection_string
28
+ else
29
+ raise "Adapter not supported."
30
+ end
31
+
32
+ @connection = @db.connection
33
+ end
34
+
35
+ #
36
+ # Convert database tables to ERD convertable Array.
37
+ #
38
+ def to_erdb
39
+ puts "\nAnalyzing database..."
40
+ @connection.tables.map do |table|
41
+ columns = @connection.columns(table).map { |column| { name: column.name, type: column.type || "unknown" } }
42
+ relations = @connection.foreign_keys(table).map do |fk|
43
+ {
44
+ from: {
45
+ table: table,
46
+ column: fk.options[:column]
47
+ },
48
+ to: {
49
+ table: fk[:to_table],
50
+ column: fk.options[:primary_key]
51
+ }
52
+ }
53
+ end
54
+
55
+ hash = { name: table, columns: columns, relations: relations }
56
+ hash[:is_join_table] = join_table?(hash)
57
+ hash
58
+ end
59
+ end
60
+
61
+ #
62
+ # Disconnect from a database.
63
+ #
64
+ def disconnect
65
+ @db.remove_connection
66
+ @connection = nil
67
+ end
68
+
69
+ private
70
+
71
+ #
72
+ # Check current table is a join table or not.
73
+ #
74
+ # @param table [Hash] The table to check.
75
+ # @return [Boolean] True if the table is a join table, false otherwise.
76
+ #
77
+ def join_table?(table)
78
+ relations = table[:relations]
79
+
80
+ # remove data like id, created_at, updated_at
81
+ columns = table[:columns].map { |c| c[:name] }.reject do |column|
82
+ %w[id created_at updated_at].include?(column)
83
+ end
84
+
85
+ if relations.size == columns.size && relations.size >= 2
86
+ columns.include?(relations[0][:from][:column]) && columns.include?(relations[1][:from][:column])
87
+ else
88
+ false
89
+ end
90
+ end
91
+
92
+ #
93
+ # Connect to a SQLite3 database.
94
+ # @param database [String] The database to connect to.
95
+ # @raise [RuntimeError] If the database does not exist.
96
+ #
97
+ def connect_sqlite3
98
+ raise "Database does not exist." unless File.exist?(@database)
99
+
100
+ @db.establish_connection(
101
+ adapter: :sqlite3,
102
+ database: @database
103
+ )
104
+ end
105
+
106
+ #
107
+ # Connect to a PostgreSQL or MySQL database.
108
+ # @param database [String] The database to connect to.
109
+ #
110
+ def connect_with_connection_string
111
+ @db.establish_connection(@database)
112
+ end
113
+ end
114
+ end
data/lib/erdb/cli.rb ADDED
@@ -0,0 +1,179 @@
1
+ require "json"
2
+
3
+ module ERDB
4
+ class Cli
5
+ class << self
6
+ #
7
+ # Start the CLI.
8
+ # @param [Array] args
9
+ # @return [void]
10
+ #
11
+ def start(_args)
12
+ ARGV.clear
13
+
14
+ welcome
15
+
16
+ db = select_database
17
+
18
+ erd_builder = select_diagram_builder
19
+
20
+ ERDB.show_join_table = ask_yes_no("\nDo you want to display join tables? (Y/n)", true)
21
+
22
+ db.connect
23
+
24
+ erd_builder.create(db.to_erdb)
25
+ rescue RuntimeError => e
26
+ puts "Error: #{e.message}"
27
+ exit 1
28
+ rescue Interrupt
29
+ puts "\n\nThank you for using ERDB!"
30
+ exit 0
31
+ end
32
+
33
+ private
34
+
35
+ #
36
+ # Ask user which database to use.
37
+ # @return [Db]
38
+ #
39
+ def select_database
40
+ data = {
41
+ sqlite3: { name: "SQLite", gem: "sqlite3" },
42
+ postgresql: { name: "PostgreSQL(Gem 'pg' must be installed)", gem: "pg" },
43
+ mysql2: { name: "MySQL(Gem 'mysql2' must be installed)", gem: "mysql2" }
44
+ }
45
+
46
+ puts "Select a database adapter:"
47
+
48
+ data.each_with_index do |v, i|
49
+ puts "#{i + 1}. #{v[1][:name]}"
50
+ end
51
+
52
+ response = ask_number(1, data.size)
53
+
54
+ adapter = data.keys[response.to_i - 1].to_sym
55
+
56
+ # check if the gem is installed
57
+ # I don't want to include the gem in the gemspec file
58
+ # cuz it's dependencies are too big and depend on the native library
59
+ # I only include sqlite3 gem cuz it's small and doesn't have any dependencies
60
+ gem = data[adapter][:gem]
61
+
62
+ begin
63
+ require gem
64
+ rescue LoadError
65
+ puts "\nError: '#{gem}' gem is not installed."
66
+ puts "Please install the gem '#{gem}' first."
67
+ puts "Run 'gem install #{gem}' to install the gem."
68
+ exit 1
69
+ end
70
+
71
+ database = if adapter == :sqlite3
72
+ ask_file "\nEnter the path to the database file:"
73
+ else
74
+ ask "\nEnter the database connection string:"
75
+ end
76
+
77
+ return SQL.new(adapter, database) if %i[sqlite3 mysql2 postgresql].include?(adapter)
78
+
79
+ raise "Invalid database adapter"
80
+ end
81
+
82
+ #
83
+ # Select a diagram builder.
84
+ # @return [ERDProvider]
85
+ #
86
+ def select_diagram_builder
87
+ data = [Azimutt, DBDiagram]
88
+
89
+ puts "\nSelect a diagram builder:"
90
+
91
+ data.each_with_index do |v, i|
92
+ puts "#{i + 1}. #{v.name.split('::').last}"
93
+ end
94
+
95
+ response = ask_number(1, data.size)
96
+
97
+ data[response.to_i - 1]
98
+ end
99
+
100
+ #
101
+ # Display welcome message.
102
+ #
103
+ def welcome
104
+ puts <<~WELCOME
105
+ .----------------. .----------------. .----------------. .----------------.
106
+ | .--------------. || .--------------. || .--------------. || .--------------. |
107
+ | | _________ | || | _______ | || | ________ | || | ______ | |
108
+ | | |_ ___ | | || | |_ __ \\ | || | |_ ___ `. | || | |_ _ \\ | |
109
+ | | | |_ \\_| | || | | |__) | | || | | | `. \\ | || | | |_) | | |
110
+ | | | _| _ | || | | __ / | || | | | | | | || | | __'. | |
111
+ | | _| |___/ | | || | _| | \\ \\_ | || | _| |___.' / | || | _| |__) | | |
112
+ | | |_________| | || | |____| |___| | || | |________.' | || | |_______/ | |
113
+ | | | || | | || | | || | | |
114
+ | '--------------' || '--------------' || '--------------' || '--------------' |
115
+ '----------------' '----------------' '----------------' '----------------'
116
+
117
+ ERDB is an automate tool to generate Entity-Relationship Diagrams from a database.
118
+ It use Azimutt and DBDiagram to generate the diagrams.
119
+
120
+ WELCOME
121
+ end
122
+
123
+ #
124
+ # Ask a question to the user.
125
+ # @param [String] question
126
+ # @return [String]
127
+ #
128
+ def ask(question = nil)
129
+ puts question if question
130
+ print "> "
131
+ gets.chomp
132
+ end
133
+
134
+ #
135
+ # Ask a number input to the user.
136
+ # @param [Integer] min
137
+ # @param [Integer] max
138
+ # @return [Integer]
139
+ #
140
+ def ask_number(min, max)
141
+ response = nil
142
+ until response.to_i.between?(min, max)
143
+ response = ask
144
+ unless response.match(/^\d+$/)
145
+ puts "Please enter a number"
146
+ response = nil
147
+ end
148
+
149
+ unless response.to_i.between?(min, max)
150
+ puts "Please enter a number between #{min} and #{max}"
151
+ response = nil
152
+ end
153
+ end
154
+ response
155
+ end
156
+
157
+ def ask_file(question)
158
+ loop do
159
+ file = ask question
160
+ return file if File.exist?(file)
161
+
162
+ puts "Invalid file path"
163
+ end
164
+ end
165
+
166
+ #
167
+ # Ask a yes/no question to the user.
168
+ # @param [String] question
169
+ # @param [Boolean] default
170
+ # @return [Boolean]
171
+ #
172
+ def ask_yes_no(question, default = true)
173
+ result = ask question
174
+
175
+ result.empty? ? default : result.downcase == "y"
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,134 @@
1
+ require "clipboard"
2
+ require "watir"
3
+
4
+ module ERDB
5
+ class Azimutt < ERDProvider
6
+ class << self
7
+ #
8
+ # Create a new ER Diagram using https://azimutt.app/.
9
+ # @param [Hash] tables
10
+ #
11
+ def create(tables)
12
+ converted_data = to_aml(tables)
13
+
14
+ Utils.display_output(converted_data, "Azimutt")
15
+
16
+ start_automation(converted_data)
17
+ end
18
+
19
+ private
20
+
21
+ #
22
+ # Start the automation process to generate the ER Diagram.
23
+ # @param [String] data
24
+ # @return [void]
25
+ #
26
+ def start_automation(data)
27
+ browser = Watir::Browser.new(ERDB.default_browser)
28
+
29
+ browser.goto "https://azimutt.app/new"
30
+
31
+ browser.span(text: "From scratch (db design)").click
32
+
33
+ browser.button(id: "create-project-btn").click
34
+
35
+ textarea = browser.textarea(id: "source-editor")
36
+ textarea.click
37
+
38
+ old_clipboard = Clipboard.paste
39
+ Clipboard.copy(data)
40
+
41
+ # set! sometimes doesn't work cuz azimutt automatically reset incorrectly formatted data
42
+ # and set is also slow as hell better to use send_keys
43
+ # sometime naive is better than smart lol
44
+ #
45
+ # textarea.set(data)
46
+
47
+ control = Utils.is_mac? ? :command : :control
48
+ browser.send_keys control, "v"
49
+
50
+ Clipboard.copy(old_clipboard)
51
+
52
+ # rubocop:disable Lint/MissingCopEnableDirective
53
+ # rubocop:disable Layout/LineLength
54
+ btn = browser.button(class: "-ml-px rounded-r-md relative inline-flex items-center p-2 border border-gray-300 text-sm font-medium focus:z-10 focus:outline-none focus:ring-1 focus:ring-primary-500 focus:border-primary-500 bg-white text-gray-700 hover:bg-gray-50")
55
+
56
+ btn.click if btn.exists?
57
+
58
+ puts "Enter 'q' to exit."
59
+
60
+ loop do
61
+ v = gets.chomp
62
+ break if v == "q"
63
+ end
64
+
65
+ browser.close
66
+ end
67
+
68
+ #
69
+ # Convert the data to AML(Azimutt Markup Language) format.
70
+ #
71
+ # @param [Hash] tables
72
+ # @return [String]
73
+ #
74
+ def to_aml(tables)
75
+ str = ""
76
+ tables.each_with_index do |table, i|
77
+ if table[:is_join_table] && !ERDB.show_join_table?
78
+ str += to_many_to_many_str(table)
79
+ next
80
+ end
81
+
82
+ str += "\n\n" if i.positive?
83
+ str += "#{table[:name]}\n"
84
+ str += table[:columns].map { |c| to_column(c[:name], c[:type]) }.join("\n")
85
+
86
+ # relations
87
+ r = table[:relations]
88
+ next if r.nil? || r.empty?
89
+
90
+ r.each do |relation|
91
+ str += "\n"
92
+ f = relation[:from]
93
+ t = relation[:to]
94
+
95
+ str += "fk #{f[:table]}.#{f[:column]} -> #{t[:table]}.#{t[:column]}"
96
+ end
97
+ end
98
+ str
99
+ end
100
+
101
+ #
102
+ # Convert a column to a string.
103
+ # @param [String] name
104
+ # @param [String] type
105
+ #
106
+ def to_column(name, type)
107
+ " #{name} #{type}"
108
+ end
109
+
110
+ #
111
+ # Convert a many-to-many table to a AML formatted string.
112
+ # @param [Hash] table
113
+ # @return [String]
114
+ #
115
+ def to_many_to_many_str(table)
116
+ str = "\n"
117
+ relations = Utils.to_many_to_many(table[:relations])
118
+
119
+ # Azimutt doesn't support many-to-many relations
120
+ # so we have to convert it to two one-to-many relations
121
+ # Really weird but does the job :/
122
+ relations.each do |relation|
123
+ relations.each do |other|
124
+ next if relation == other
125
+
126
+ str += "\nfk: #{relation} -> #{other}\n"
127
+ end
128
+ end
129
+
130
+ str
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,121 @@
1
+ require "clipboard"
2
+ require "watir"
3
+
4
+ module ERDB
5
+ class DBDiagram < ERDProvider
6
+ class << self
7
+ #
8
+ # Create a new ER Diagram using https://dbdiagram.io
9
+ # @param [Hash] tables
10
+ #
11
+ def create(tables)
12
+ converted_data = to_dbdiagram_format(tables)
13
+
14
+ Utils.display_output(converted_data, "DBDiagram")
15
+
16
+ start_automation(converted_data)
17
+ end
18
+
19
+ private
20
+
21
+ #
22
+ # Start the automation process to generate the ER Diagram.
23
+ # @param [String] data
24
+ # @return [void]
25
+ #
26
+ def start_automation(data)
27
+ browser = Watir::Browser.new(ERDB.default_browser)
28
+
29
+ browser.goto "https://dbdiagram.io/d"
30
+
31
+ editor = browser.div(class: "view-lines monaco-mouse-cursor-text")
32
+ editor.click
33
+
34
+ control = Utils.is_mac? ? :command : :control
35
+
36
+ browser.send_keys control, "a"
37
+ browser.send_keys :delete
38
+
39
+ old_clipboard = Clipboard.paste
40
+ # Yep, I know this is ugly.
41
+ # But DBDiagram don't use input element for editor. -_-
42
+ Clipboard.copy(data)
43
+
44
+ browser.send_keys control, "v"
45
+
46
+ Clipboard.copy(old_clipboard)
47
+
48
+ puts "Enter 'q' to exit."
49
+
50
+ loop do
51
+ v = gets.chomp
52
+ break if v == "q"
53
+ end
54
+
55
+ browser.close
56
+ end
57
+
58
+ #
59
+ # Convert the data DBDiagram string format.
60
+ #
61
+ # @param [Hash] tables
62
+ # @return [String]
63
+ #
64
+ def to_dbdiagram_format(tables)
65
+ str = ""
66
+ tables.each_with_index do |table, i|
67
+ if table[:is_join_table] && !ERDB.show_join_table?
68
+ str += to_many_to_many_str(table)
69
+ next
70
+ end
71
+
72
+ str += "\n" if i.positive?
73
+ str += "Table #{table[:name]} {\n"
74
+ str += table[:columns].map { |c| to_column(c[:name], c[:type]) }.join("\n")
75
+ str += "\n}\n"
76
+
77
+ r = table[:relations]
78
+ next if r.nil? || r.empty?
79
+
80
+ r.each do |relation|
81
+ str += "\n"
82
+ f = relation[:from]
83
+ t = relation[:to]
84
+
85
+ str += "Ref: #{f[:table]}.#{f[:column]} > #{t[:table]}.#{t[:column]}"
86
+ end
87
+
88
+ str += "\n"
89
+ end
90
+ str
91
+ end
92
+
93
+ #
94
+ # Convert a column to a string.
95
+ # @param [String] name
96
+ # @param [String] type
97
+ #
98
+ def to_column(name, type)
99
+ " #{name} #{type}"
100
+ end
101
+
102
+ #
103
+ # Convert a many-to-many table to a dbdiagram formatted string.
104
+ # @param [Hash] table
105
+ # @return [String]
106
+ #
107
+ def to_many_to_many_str(table)
108
+ str = ""
109
+ relations = Utils.to_many_to_many(table[:relations])
110
+
111
+ relations.each_with_index do |relation, i|
112
+ next if i.zero?
113
+
114
+ str += "\nRef: #{relations.first} <> #{relation}\n"
115
+ end
116
+
117
+ str
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,11 @@
1
+ module ERDB
2
+ class ERDProvider
3
+ #
4
+ # Create a new ER Diagram.
5
+ # @param [Hash] tables
6
+ #
7
+ def create(tables)
8
+ raise NotImplementedError
9
+ end
10
+ end
11
+ end
data/lib/erdb/utils.rb ADDED
@@ -0,0 +1,49 @@
1
+ module ERDB
2
+ class Utils
3
+ class << self
4
+ #
5
+ # Display the ER Diagram required data.
6
+ # @param [String] data
7
+ # @param [String] provider
8
+ # @return [void]
9
+ #
10
+ def display_output(data, provider)
11
+ puts "### Copy following output to #{provider} if unexpected error happen ###"
12
+ puts "### Start of output ###\n\n"
13
+ puts data
14
+ puts "\n### End of output ###"
15
+ end
16
+
17
+ #
18
+ # Check if the current OS is macOS.
19
+ # @return [Boolean]
20
+ def is_mac?
21
+ RbConfig::CONFIG["host_os"] =~ /darwin|mac os/
22
+ end
23
+
24
+ #
25
+ # Convert the relations to ER Diagram format.
26
+ # @param [Array] relations
27
+ # @return [Array]
28
+ # @example
29
+ # [
30
+ # {
31
+ # from: {
32
+ # table: "users",
33
+ # column: "id"
34
+ # },
35
+ # to: {
36
+ # table: "posts",
37
+ # column: "user_id"
38
+ # }
39
+ # }
40
+ # ]
41
+ # # => ["users.id", "posts.user_id"]
42
+ def to_many_to_many(relations)
43
+ relations.map do |relation|
44
+ "#{relation[:to][:table]}.#{relation[:to][:column]}"
45
+ end.uniq
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module ERDB
2
+ VERSION = "1.0.0".freeze
3
+ end
data/lib/erdb.rb ADDED
@@ -0,0 +1,38 @@
1
+ require_relative "erdb/cli"
2
+ require_relative "erdb/version"
3
+ require_relative "erdb/utils"
4
+ require_relative "erdb/providers/erd_provider"
5
+
6
+ module ERDB
7
+ autoload :SQL, File.expand_path("erdb/adapters/sql", __dir__)
8
+ autoload :Azimutt, File.expand_path("erdb/providers/azimutt", __dir__)
9
+ autoload :DBDiagram, File.expand_path("erdb/providers/dbdiagram", __dir__)
10
+
11
+ class << self
12
+ attr_writer :default_timeout, :default_browser, :show_join_table
13
+
14
+ #
15
+ # Default wait time for wait methods.
16
+ # @return [Integer] Default wait time in seconds.
17
+ #
18
+ def default_timeout
19
+ @default_timeout ||= 30
20
+ end
21
+
22
+ #
23
+ # Default browser to use for automation.
24
+ # @return [Symbol]
25
+ #
26
+ def default_browser
27
+ @default_browser ||= :chrome
28
+ end
29
+
30
+ #
31
+ # Show join table in the diagram.
32
+ # @return [Boolean]
33
+ #
34
+ def show_join_table?
35
+ @show_join_table.nil? ? true : @show_join_table
36
+ end
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: erdb
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Wai Yan Phyo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '7.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '7.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: clipboard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: watir
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '7.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '7.2'
69
+ description: ERDB is a Ruby Gem for generation Entity-Relationship Diagrams (ERD).
70
+ email: oyhpnayiaw@gmail.com
71
+ executables:
72
+ - erdb
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - CHANGES.md
77
+ - README.md
78
+ - bin/erdb
79
+ - lib/erdb.rb
80
+ - lib/erdb/adapters/db.rb
81
+ - lib/erdb/adapters/nosql.rb
82
+ - lib/erdb/adapters/sql.rb
83
+ - lib/erdb/cli.rb
84
+ - lib/erdb/providers/azimutt.rb
85
+ - lib/erdb/providers/dbdiagram.rb
86
+ - lib/erdb/providers/erd_provider.rb
87
+ - lib/erdb/utils.rb
88
+ - lib/erdb/version.rb
89
+ homepage: https://github.com/oyhpnayiaw/erdb
90
+ licenses:
91
+ - MIT
92
+ metadata:
93
+ source_code_uri: https://github.com/oyhpnayiaw/erdb
94
+ rubygems_mfa_required: 'true'
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 2.7.0
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubygems_version: 3.4.10
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: ERDB is a Ruby Gem for generation Entity-Relationship Diagrams (ERD).
114
+ test_files: []