rails-mermaid_erd_markdown 0.1.0 → 0.3.0
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.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS.md +1 -0
- data/.github/workflows/CI.yml +42 -0
- data/.github/workflows/codeql.yml +93 -0
- data/.gitignore +45 -0
- data/.rubocop.yml +37 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +231 -0
- data/LICENSE.txt +21 -0
- data/README.md +36 -9
- data/Rakefile +1 -1
- data/bin/console +15 -0
- data/bin/rubocop +29 -0
- data/bin/setup +8 -0
- data/docs/examples/erd.yml +1 -1
- data/lib/rails-mermaid_erd_markdown/configuration.rb +22 -13
- data/lib/rails-mermaid_erd_markdown/generator.rb +169 -0
- data/lib/rails-mermaid_erd_markdown/markdown_document.rb +104 -0
- data/lib/rails-mermaid_erd_markdown/source_data.rb +63 -0
- data/lib/rails-mermaid_erd_markdown/version.rb +1 -1
- data/lib/rails-mermaid_erd_markdown.rb +3 -92
- data/rails-mermaid_erd_markdown.gemspec +37 -0
- data/sig/rails/mermaid_erd_markdown.rbs +6 -0
- data/test/example_output/mock_ERD.md +48 -0
- data/test/example_output/mock_ERD_index.md +10 -0
- data/test/example_output/mock_ERD_model.md +46 -0
- data/test/mock_data/models.rb +105 -0
- data/test/test_helper.rb +10 -0
- data/test/test_rails/rails-mermaid_erd_markdown/test_generator.rb +54 -0
- data/test/test_rails/rails-mermaid_erd_markdown/test_markdown_document.rb +76 -0
- data/test/test_rails/rails-mermaid_erd_markdown/test_source_data.rb +70 -0
- data/test/test_rails/test_rails-mermaid_erd_markdown.rb +9 -0
- metadata +46 -2
data/bin/rubocop
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/bin/setup
ADDED
data/docs/examples/erd.yml
CHANGED
@@ -1,20 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "yaml"
|
2
|
-
require "logger"
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
module MermaidErdMarkdown
|
6
|
+
class Configuration
|
7
|
+
attr_accessor :output_path, :split_output, :relationship_depth
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def initialize
|
10
|
+
config = {
|
11
|
+
output_path: "app/models/ERD.md",
|
12
|
+
split_output: false,
|
13
|
+
relationship_depth: 1
|
14
|
+
}
|
15
|
+
erd_config_path = "erd.yml"
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
begin
|
18
|
+
erd_yml = YAML.safe_load File.open(erd_config_path)
|
19
|
+
@output_path = erd_yml["erd"]["output_path"] || config[:output_path]
|
20
|
+
@split_output = erd_yml["erd"]["split_output"] || config[:split_output]
|
21
|
+
@relationship_depth = erd_yml["erd"]["relationship_depth"] || config[:relationship_depth]
|
22
|
+
rescue StandardError
|
23
|
+
@output_path = config[:output_path]
|
24
|
+
@split_output = config[:split_output]
|
25
|
+
@relationship_depth = config[:relationship_depth]
|
26
|
+
end
|
18
27
|
end
|
19
28
|
end
|
20
29
|
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "configuration"
|
4
|
+
require_relative "markdown_document"
|
5
|
+
require_relative "source_data"
|
6
|
+
require "digest/md5"
|
7
|
+
require "logger"
|
8
|
+
require "pathname"
|
9
|
+
|
10
|
+
module MermaidErdMarkdown
|
11
|
+
class Generator
|
12
|
+
attr_writer :logger
|
13
|
+
|
14
|
+
def self.generate
|
15
|
+
new.generate
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate
|
19
|
+
return unless find_or_create_output
|
20
|
+
return unless erd_changed?
|
21
|
+
|
22
|
+
update_erd
|
23
|
+
|
24
|
+
update_split_erds if configuration.split_output
|
25
|
+
end
|
26
|
+
|
27
|
+
def index_markdown(files)
|
28
|
+
MermaidErdMarkdown::MarkdownDocument.create do |doc|
|
29
|
+
doc.add(doc.header("Entity Relationship Diagrams"))
|
30
|
+
doc.add(
|
31
|
+
"Each model has its own ERD diagram. The diagram shows the " \
|
32
|
+
"selected model, plus #{configuration.relationship_depth} " \
|
33
|
+
"associated model(s) deep. Click on the model name to view " \
|
34
|
+
"the diagram.\n"
|
35
|
+
)
|
36
|
+
doc.add(doc.subheader("Models"))
|
37
|
+
files.each do |model, path|
|
38
|
+
doc.add(doc.list_item(doc.link(model, "../#{path}")))
|
39
|
+
end
|
40
|
+
doc.add("")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def model_markdown(output)
|
45
|
+
MermaidErdMarkdown::MarkdownDocument.create do |doc|
|
46
|
+
model_name = output[:Models].first[:ModelName]
|
47
|
+
doc.add(doc.header("#{model_name} Entity-Relationship Diagram"))
|
48
|
+
doc.add(doc.subheader("Associated Models"))
|
49
|
+
output[:Models].each do |model|
|
50
|
+
next if model[:ModelName] == model_name
|
51
|
+
|
52
|
+
model_path = "../#{output_path(model[:ModelName])}"
|
53
|
+
|
54
|
+
doc.add(doc.list_item(doc.link(model[:ModelName], model_path)))
|
55
|
+
end
|
56
|
+
doc.add("")
|
57
|
+
doc.add(doc.subheader("Entity-Relationship Diagram"))
|
58
|
+
doc.add(mermaid_markdown(output))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def mermaid_markdown(source)
|
63
|
+
MermaidErdMarkdown::MarkdownDocument.create do
|
64
|
+
erd do
|
65
|
+
add(
|
66
|
+
source[:Models].map do |model|
|
67
|
+
erd_table(model[:TableName], model[:ModelName]) do
|
68
|
+
model[:Columns].map do |column|
|
69
|
+
erd_table_column(column)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
)
|
74
|
+
add(
|
75
|
+
source[:Relations].map do |relation|
|
76
|
+
erd_relation(relation)
|
77
|
+
end
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def comprehensive_erd
|
86
|
+
@comprehensive_erd ||= mermaid_markdown(source_data.data)
|
87
|
+
end
|
88
|
+
|
89
|
+
def configuration
|
90
|
+
@configuration ||= MermaidErdMarkdown::Configuration.new
|
91
|
+
end
|
92
|
+
|
93
|
+
def erd_changed?
|
94
|
+
# check if two diagrams are the same by comparing their MD5 hashes
|
95
|
+
existing_erd_hash = Digest::MD5.hexdigest(File.read(output_path))
|
96
|
+
new_erd_hash = Digest::MD5.hexdigest(comprehensive_erd)
|
97
|
+
|
98
|
+
return true if existing_erd_hash != new_erd_hash
|
99
|
+
|
100
|
+
logger.info("ERD already exists and is up to date. Skipping...")
|
101
|
+
|
102
|
+
false
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_or_create_output
|
106
|
+
return true if output_path.exist?
|
107
|
+
|
108
|
+
logger.info("ERD does not currently exist at result path. Creating...")
|
109
|
+
begin
|
110
|
+
write_file("", output_path)
|
111
|
+
logger.info("ERD successfully created at #{output_path}")
|
112
|
+
rescue StandardError
|
113
|
+
logger.info("Could not create ERD. Output path is invalid.")
|
114
|
+
|
115
|
+
false
|
116
|
+
end
|
117
|
+
|
118
|
+
true
|
119
|
+
end
|
120
|
+
|
121
|
+
def logger
|
122
|
+
@logger ||= Logger.new($stdout).tap do |log|
|
123
|
+
log.progname = self.class.name.split("::").first
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def output_path(extension = nil)
|
128
|
+
return Pathname.new(configuration.output_path) unless extension
|
129
|
+
|
130
|
+
Pathname.new(configuration.output_path).sub_ext("_#{extension}.md")
|
131
|
+
end
|
132
|
+
|
133
|
+
def source_data
|
134
|
+
@source_data ||= MermaidErdMarkdown::SourceData.new
|
135
|
+
end
|
136
|
+
|
137
|
+
def update_erd
|
138
|
+
logger.info("ERD writing to #{output_path}...")
|
139
|
+
write_file(comprehensive_erd, output_path)
|
140
|
+
logger.info("ERD successfully written")
|
141
|
+
end
|
142
|
+
|
143
|
+
def update_split_erds
|
144
|
+
# first remove all existing model ERD files
|
145
|
+
Dir.glob(output_path.sub_ext("_*.md")).each do |file|
|
146
|
+
File.delete(file)
|
147
|
+
end
|
148
|
+
|
149
|
+
files = {}
|
150
|
+
|
151
|
+
depth = configuration.relationship_depth
|
152
|
+
|
153
|
+
source_data.split_output(depth).each do |output|
|
154
|
+
model_name = output[:Models].first[:ModelName]
|
155
|
+
model_path = output_path(model_name)
|
156
|
+
write_file(model_markdown(output), model_path)
|
157
|
+
logger.info("ERD successfully written to #{model_path}")
|
158
|
+
files[model_name] = model_path
|
159
|
+
end
|
160
|
+
|
161
|
+
index_path = output_path("index")
|
162
|
+
write_file(index_markdown(files), index_path)
|
163
|
+
end
|
164
|
+
|
165
|
+
def write_file(new_erd, path)
|
166
|
+
File.write(path, new_erd)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MermaidErdMarkdown
|
4
|
+
class MarkdownDocument
|
5
|
+
attr_accessor :is_show_key, :is_show_comment
|
6
|
+
|
7
|
+
def self.create(&block)
|
8
|
+
new.generate(&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@is_show_key = true
|
13
|
+
@is_show_comment = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(element)
|
17
|
+
document << element
|
18
|
+
end
|
19
|
+
|
20
|
+
def document
|
21
|
+
@document ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def erd(&block)
|
25
|
+
add(erd_header)
|
26
|
+
block.arity == 1 ? block[self] : instance_eval(&block)
|
27
|
+
add(erd_footer)
|
28
|
+
end
|
29
|
+
|
30
|
+
def erd_footer
|
31
|
+
"```"
|
32
|
+
end
|
33
|
+
|
34
|
+
def erd_header
|
35
|
+
[
|
36
|
+
"```mermaid",
|
37
|
+
"erDiagram",
|
38
|
+
" %% --------------------------------------------------------",
|
39
|
+
" %% Entity-Relationship Diagram",
|
40
|
+
" %% --------------------------------------------------------",
|
41
|
+
""
|
42
|
+
].join("\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
def erd_relation(relation)
|
46
|
+
left_model_name = relation[:LeftModelName].tr(":", "-")
|
47
|
+
right_model_name = relation[:RightModelName].tr(":", "-")
|
48
|
+
comment = is_show_comment ? ": \"#{relation[:Comment]}\"" : ": \"\""
|
49
|
+
|
50
|
+
" #{left_model_name} #{relation[:LeftValue]}" \
|
51
|
+
"#{relation[:Line]}#{relation[:RightValue]} " \
|
52
|
+
"#{right_model_name} #{comment}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def erd_table(table_name, model_name)
|
56
|
+
lines = [erd_table_header(table_name, model_name)]
|
57
|
+
lines << yield
|
58
|
+
lines << erd_table_footer
|
59
|
+
lines.join("\n")
|
60
|
+
end
|
61
|
+
|
62
|
+
def erd_table_column(column)
|
63
|
+
key = is_show_key ? column[:key] : ""
|
64
|
+
line = " #{column[:type]} #{column[:name]}"
|
65
|
+
line << " #{key}" unless key.empty?
|
66
|
+
line
|
67
|
+
end
|
68
|
+
|
69
|
+
def erd_table_header(table_name, model_name)
|
70
|
+
[
|
71
|
+
" %% table name: #{table_name}",
|
72
|
+
" #{model_name.tr(":", "-")}{"
|
73
|
+
].join("\n")
|
74
|
+
end
|
75
|
+
|
76
|
+
def erd_table_footer
|
77
|
+
[
|
78
|
+
" }",
|
79
|
+
""
|
80
|
+
].join("\n")
|
81
|
+
end
|
82
|
+
|
83
|
+
def header(text)
|
84
|
+
"# #{text}\n"
|
85
|
+
end
|
86
|
+
|
87
|
+
def generate(&block)
|
88
|
+
block.arity == 1 ? block[self] : instance_eval(&block)
|
89
|
+
document.join("\n")
|
90
|
+
end
|
91
|
+
|
92
|
+
def link(text, url)
|
93
|
+
"[#{text}](#{url})"
|
94
|
+
end
|
95
|
+
|
96
|
+
def list_item(text)
|
97
|
+
"- #{text}"
|
98
|
+
end
|
99
|
+
|
100
|
+
def subheader(text)
|
101
|
+
"## #{text}\n"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails-mermaid_erd"
|
4
|
+
|
5
|
+
module MermaidErdMarkdown
|
6
|
+
class SourceData
|
7
|
+
def data
|
8
|
+
@data ||= RailsMermaidErd::Builder.model_data
|
9
|
+
end
|
10
|
+
|
11
|
+
def split_output(depth = 1)
|
12
|
+
source_models = data[:Models]
|
13
|
+
source_relations = data[:Relations]
|
14
|
+
output = []
|
15
|
+
|
16
|
+
source_models.each do |model|
|
17
|
+
model_names = [model[:ModelName]]
|
18
|
+
search_models = model_names
|
19
|
+
relations = []
|
20
|
+
|
21
|
+
depth.times do
|
22
|
+
found_relations = []
|
23
|
+
next_search_models = []
|
24
|
+
search_models.each do |search_model|
|
25
|
+
found_relations += related_models(search_model, source_relations)
|
26
|
+
next_search_models += related_model_names(search_model, found_relations)
|
27
|
+
end
|
28
|
+
search_models = next_search_models
|
29
|
+
model_names += search_models
|
30
|
+
relations += found_relations
|
31
|
+
end
|
32
|
+
|
33
|
+
output << {
|
34
|
+
Models: models(model_names.uniq, source_models),
|
35
|
+
Relations: relations.uniq
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
output
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def models(model_names, source_models)
|
45
|
+
model_names.map do |model_name|
|
46
|
+
source_models.find { |m| m[:ModelName] == model_name }
|
47
|
+
end.compact
|
48
|
+
end
|
49
|
+
|
50
|
+
def related_model_names(model_name, relations)
|
51
|
+
relations.map do |r|
|
52
|
+
r[:LeftModelName] == model_name ? r[:RightModelName] : r[:LeftModelName]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def related_models(model_name, relations)
|
57
|
+
relations.select do |relation|
|
58
|
+
relation[:LeftModelName] == model_name ||
|
59
|
+
relation[:RightModelName] == model_name
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,108 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "rails-mermaid_erd_markdown/
|
4
|
-
require "digest/md5"
|
3
|
+
require_relative "rails-mermaid_erd_markdown/generator"
|
5
4
|
require "rake"
|
6
5
|
require "rake/dsl_definition"
|
7
|
-
require "pathname"
|
8
|
-
require "logger"
|
9
6
|
|
10
7
|
module MermaidErdMarkdown
|
11
8
|
extend Rake::DSL
|
12
9
|
|
13
10
|
class << self
|
14
|
-
attr_writer :logger
|
15
|
-
|
16
|
-
def logger
|
17
|
-
@logger ||= Logger.new($stdout).tap do |log|
|
18
|
-
log.progname = name
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def configuration
|
23
|
-
@configuration ||= MermaidErdMarkdown::Configuration.new
|
24
|
-
end
|
25
|
-
|
26
11
|
def perform
|
27
|
-
|
28
|
-
existing_erd_path = Pathname.new(configuration.output_path)
|
29
|
-
|
30
|
-
unless existing_erd_path.exist?
|
31
|
-
logger.info("ERD does not currently exist at result path. Creating...")
|
32
|
-
begin
|
33
|
-
create_erd_file(new_erd)
|
34
|
-
logger.info("ERD successfully created at #{configuration.output_path}")
|
35
|
-
rescue StandardError
|
36
|
-
logger.info("Could not create ERD. Output path is invalid.")
|
37
|
-
end
|
38
|
-
|
39
|
-
return
|
40
|
-
end
|
41
|
-
|
42
|
-
existing_erd = File.read(existing_erd_path)
|
43
|
-
update_erd_file(existing_erd, new_erd)
|
44
|
-
end
|
45
|
-
|
46
|
-
def update_erd_file(current_erd, new_erd)
|
47
|
-
# check if two diagrams are the same by comparing their MD5 hashes
|
48
|
-
if Digest::MD5.hexdigest(current_erd) == Digest::MD5.hexdigest(new_erd)
|
49
|
-
logger.info("ERD already exists and is up to date. Skipping...")
|
50
|
-
return
|
51
|
-
end
|
52
|
-
|
53
|
-
logger.info("ERD already exists but is out of date. Overwriting...")
|
54
|
-
File.write(configuration.output_path, new_erd)
|
55
|
-
logger.info("ERD successfully updated")
|
56
|
-
|
57
|
-
nil
|
58
|
-
end
|
59
|
-
|
60
|
-
def create_erd_file(erd)
|
61
|
-
File.write(configuration.output_path, erd)
|
62
|
-
|
63
|
-
nil
|
64
|
-
end
|
65
|
-
|
66
|
-
def generate_mermaid_erd
|
67
|
-
data = RailsMermaidErd::Builder.model_data
|
68
|
-
|
69
|
-
is_show_key = true
|
70
|
-
is_show_relation_comment = true
|
71
|
-
|
72
|
-
lines = ["```mermaid"]
|
73
|
-
lines << "erDiagram"
|
74
|
-
lines << " %% --------------------------------------------------------"
|
75
|
-
lines << " %% Entity-Relationship Diagram"
|
76
|
-
lines << " %% --------------------------------------------------------"
|
77
|
-
lines << ""
|
78
|
-
|
79
|
-
data[:Models].each do |model|
|
80
|
-
lines << " %% table name: #{model[:TableName]}"
|
81
|
-
lines << " #{model[:ModelName].tr(":", "-")}{"
|
82
|
-
|
83
|
-
model[:Columns].each do |column|
|
84
|
-
key = is_show_key ? column[:key] : ""
|
85
|
-
lines << " #{column[:type]} #{column[:name]} #{key} "
|
86
|
-
end
|
87
|
-
|
88
|
-
lines << " }"
|
89
|
-
lines << ""
|
90
|
-
end
|
91
|
-
|
92
|
-
data[:Relations].each do |relation|
|
93
|
-
left_model_name = relation[:LeftModelName].tr(":", "-")
|
94
|
-
right_model_name = relation[:RightModelName].tr(":", "-")
|
95
|
-
comment = is_show_relation_comment ? ": \"#{relation[:Comment]}\"" : ": \"\""
|
96
|
-
|
97
|
-
lines << " #{left_model_name} #{relation[:LeftValue]}#{relation[:Line]}#{relation[:RightValue]} #{right_model_name} #{comment}"
|
98
|
-
end
|
99
|
-
|
100
|
-
lines << "```"
|
101
|
-
lines.join("\n")
|
12
|
+
MermaidErdMarkdown::Generator.generate
|
102
13
|
end
|
103
14
|
end
|
104
15
|
|
105
|
-
desc "Generate/update mermaid ERD diagram for database Models."
|
16
|
+
desc "Generate/update mermaid ERD diagram(s) for database Models."
|
106
17
|
task generate_erd: :environment do
|
107
18
|
perform
|
108
19
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/rails-mermaid_erd_markdown/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rails-mermaid_erd_markdown"
|
7
|
+
spec.version = MermaidErdMarkdown::VERSION
|
8
|
+
spec.authors = ["humzahkiani"]
|
9
|
+
spec.email = ["89326566+humzahkiani@users.noreply.github.com"]
|
10
|
+
|
11
|
+
spec.summary = "This is a rails gem that extends the rails-mermaid_erd gem to generate a mermaid ERD for Rails " \
|
12
|
+
"Models in markdown directly in source code."
|
13
|
+
spec.homepage = "https://github.com/humzahkiani/rails-mermaid_erd_markdown"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 2.6.0"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/humzahkiani/rails-mermaid_erd_markdown"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/humzahkiani/rails-mermaid_erd_markdown/blob/main/CHANGELOG.md"
|
20
|
+
spec.metadata["github_repo"] = "ssh://github.com/humzahkiani/rails-mermaid_erd_markdown"
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0")
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
# Runtime Dependencies
|
31
|
+
spec.add_dependency "rails", ">= 5.2"
|
32
|
+
spec.add_dependency "rails-mermaid_erd", "~> 0.4.2"
|
33
|
+
|
34
|
+
# For more information and examples about making a new gem, check out our
|
35
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
36
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
37
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
```mermaid
|
2
|
+
erDiagram
|
3
|
+
%% --------------------------------------------------------
|
4
|
+
%% Entity-Relationship Diagram
|
5
|
+
%% --------------------------------------------------------
|
6
|
+
|
7
|
+
%% table name: users
|
8
|
+
User{
|
9
|
+
integer id PK
|
10
|
+
string name
|
11
|
+
string email
|
12
|
+
datetime created_at
|
13
|
+
datetime updated_at
|
14
|
+
}
|
15
|
+
|
16
|
+
%% table name: profiles
|
17
|
+
Profile{
|
18
|
+
integer id PK
|
19
|
+
text bio
|
20
|
+
integer user_id FK
|
21
|
+
datetime created_at
|
22
|
+
datetime updated_at
|
23
|
+
}
|
24
|
+
|
25
|
+
%% table name: articles
|
26
|
+
Article{
|
27
|
+
integer id PK
|
28
|
+
string title
|
29
|
+
text content
|
30
|
+
integer user_id FK
|
31
|
+
datetime created_at
|
32
|
+
datetime updated_at
|
33
|
+
}
|
34
|
+
|
35
|
+
%% table name: comments
|
36
|
+
Comment{
|
37
|
+
integer id PK
|
38
|
+
string commenter
|
39
|
+
text body
|
40
|
+
integer article_id FK
|
41
|
+
datetime created_at
|
42
|
+
datetime updated_at
|
43
|
+
}
|
44
|
+
|
45
|
+
Article }o--|| User : "BT:user"
|
46
|
+
Profile }o--|| User : "BT:user"
|
47
|
+
Comment }o--|| Article : "BT:article"
|
48
|
+
```
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Entity Relationship Diagrams
|
2
|
+
|
3
|
+
Each model has its own ERD diagram. The diagram shows the selected model, plus 1 associated model(s) deep. Click on the model name to view the diagram.
|
4
|
+
|
5
|
+
## Models
|
6
|
+
|
7
|
+
- [User](../User.md)
|
8
|
+
- [Profile](../Profile.md)
|
9
|
+
- [Article](../Article.md)
|
10
|
+
- [Comment](../Comment.md)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# User Entity-Relationship Diagram
|
2
|
+
|
3
|
+
## Associated Models
|
4
|
+
|
5
|
+
- [Article](../app/models/ERD_Article.md)
|
6
|
+
- [Profile](../app/models/ERD_Profile.md)
|
7
|
+
|
8
|
+
## Entity-Relationship Diagram
|
9
|
+
|
10
|
+
```mermaid
|
11
|
+
erDiagram
|
12
|
+
%% --------------------------------------------------------
|
13
|
+
%% Entity-Relationship Diagram
|
14
|
+
%% --------------------------------------------------------
|
15
|
+
|
16
|
+
%% table name: users
|
17
|
+
User{
|
18
|
+
integer id PK
|
19
|
+
string name
|
20
|
+
string email
|
21
|
+
datetime created_at
|
22
|
+
datetime updated_at
|
23
|
+
}
|
24
|
+
|
25
|
+
%% table name: articles
|
26
|
+
Article{
|
27
|
+
integer id PK
|
28
|
+
string title
|
29
|
+
text content
|
30
|
+
integer user_id FK
|
31
|
+
datetime created_at
|
32
|
+
datetime updated_at
|
33
|
+
}
|
34
|
+
|
35
|
+
%% table name: profiles
|
36
|
+
Profile{
|
37
|
+
integer id PK
|
38
|
+
text bio
|
39
|
+
integer user_id FK
|
40
|
+
datetime created_at
|
41
|
+
datetime updated_at
|
42
|
+
}
|
43
|
+
|
44
|
+
Article }o--|| User : "BT:user"
|
45
|
+
Profile }o--|| User : "BT:user"
|
46
|
+
```
|