jw-rails-erd 1.4.5
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 +7 -0
- data/README.md +86 -0
- data/Rakefile +20 -0
- data/bin/erd +4 -0
- data/lib/generators/erd/USAGE +4 -0
- data/lib/generators/erd/install_generator.rb +14 -0
- data/lib/generators/erd/templates/auto_generate_diagram.rake +6 -0
- data/lib/rails-erd.rb +1 -0
- data/lib/rails_erd/cli.rb +164 -0
- data/lib/rails_erd/config.rb +97 -0
- data/lib/rails_erd/custom.rb +99 -0
- data/lib/rails_erd/diagram/graphviz.rb +295 -0
- data/lib/rails_erd/diagram/templates/node.html.erb +14 -0
- data/lib/rails_erd/diagram/templates/node.record.erb +4 -0
- data/lib/rails_erd/diagram.rb +188 -0
- data/lib/rails_erd/domain/attribute.rb +160 -0
- data/lib/rails_erd/domain/entity.rb +104 -0
- data/lib/rails_erd/domain/relationship/cardinality.rb +118 -0
- data/lib/rails_erd/domain/relationship.rb +203 -0
- data/lib/rails_erd/domain/specialization.rb +90 -0
- data/lib/rails_erd/domain.rb +153 -0
- data/lib/rails_erd/railtie.rb +10 -0
- data/lib/rails_erd/tasks.rake +58 -0
- data/lib/rails_erd/version.rb +4 -0
- data/lib/rails_erd.rb +73 -0
- data/lib/tasks/auto_generate_diagram.rake +21 -0
- data/test/support_files/erdconfig.another_example +3 -0
- data/test/support_files/erdconfig.example +19 -0
- data/test/support_files/erdconfig.exclude.example +19 -0
- data/test/test_helper.rb +160 -0
- data/test/unit/attribute_test.rb +316 -0
- data/test/unit/cardinality_test.rb +123 -0
- data/test/unit/config_test.rb +110 -0
- data/test/unit/diagram_test.rb +352 -0
- data/test/unit/domain_test.rb +258 -0
- data/test/unit/entity_test.rb +252 -0
- data/test/unit/graphviz_test.rb +461 -0
- data/test/unit/rake_task_test.rb +174 -0
- data/test/unit/relationship_test.rb +476 -0
- data/test/unit/specialization_test.rb +67 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 479e99642119a6eb335c9b9c97eed2e0e59ebf86
|
4
|
+
data.tar.gz: a3593fb95a3f2d816660964734e20356921917c1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2460431f9ec8fc7daa093b4ecb86e12bea5a7ab471e6db8e309b2c3ecf37f1f9c9acfe87ec2c66e88b7780c0d5701cfeaddaf10e1b54a3221d80d3025ada50ef
|
7
|
+
data.tar.gz: ef125a202ce97ba684ddea1b4344656d54f025a45e857d24e97c35ba42373b4d810bbb4327b58805ffbd04a19b7a0d7780f51b340be9f1847fbaf5754fd5c8bc
|
data/README.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
Rails ERD - Generate Entity-Relationship Diagrams for Rails applications
|
2
|
+
========================================================================
|
3
|
+
[](https://travis-ci.org/voormedia/rails-erd) [](https://codeclimate.com/github/voormedia/rails-erd)
|
4
|
+
|
5
|
+
[Rails ERD](http://voormedia.github.io/rails-erd/) is a gem that allows you to easily generate a diagram based on your application's Active Record models. The diagram gives an overview of how your models are related. Having a diagram that describes your models is perfect documentation for your application.
|
6
|
+
|
7
|
+
The second goal of Rails ERD is to provide you with a tool to inspect your application's domain model. If you don't like the default output, it is very easy to use the API to build your own diagrams.
|
8
|
+
|
9
|
+
Rails ERD was created specifically for Rails and works on versions 3.0-4.2. It uses Active Record's built-in reflection capabilities to figure out how your models are associated.
|
10
|
+
|
11
|
+
|
12
|
+
Preview
|
13
|
+
-------
|
14
|
+
|
15
|
+
Here's an example entity-relationship diagram that was generated by Rails ERD:
|
16
|
+
|
17
|
+

|
18
|
+
|
19
|
+
Browse the [gallery](http://voormedia.github.io/rails-erd/gallery.html) for more example diagrams.
|
20
|
+
|
21
|
+
|
22
|
+
Requirements
|
23
|
+
---------------
|
24
|
+
|
25
|
+
* Ruby 1.9.3+
|
26
|
+
* ActiveRecord 3.x
|
27
|
+
|
28
|
+
Getting started
|
29
|
+
---------------
|
30
|
+
|
31
|
+
See the [installation instructions](http://voormedia.github.io/rails-erd/install.html) for a complete description of how to install Rails ERD. Here's a summary:
|
32
|
+
|
33
|
+
* Install Graphviz 2.22+ ([how?](http://voormedia.github.io/rails-erd/install.html))
|
34
|
+
|
35
|
+
* Add <tt>gem "rails-erd"</tt> to your application's Gemfile
|
36
|
+
|
37
|
+
* Run <tt>bundle exec erd</tt>
|
38
|
+
|
39
|
+
### Configuration
|
40
|
+
|
41
|
+
|
42
|
+
Rails ERD has the ability to be configured via the command line or through the use of a YAML file with configuration options set. It will look for this file first at `~/.erdconfig` and then `./.erdconfig` (which will override any settings in `~/.erdconfig`). The format of the file is as follows (shown here with the default settings used if no `.erdconfig` is found). More information on [customization options](http://voormedia.github.io/rails-erd/customise.html) can be found in Rails ERD's project documentation.
|
43
|
+
|
44
|
+
```
|
45
|
+
attributes:
|
46
|
+
- content
|
47
|
+
- foreign_key
|
48
|
+
- inheritance
|
49
|
+
disconnected: true
|
50
|
+
filename: erd
|
51
|
+
filetype: pdf
|
52
|
+
indirect: true
|
53
|
+
inheritance: false
|
54
|
+
markup: true
|
55
|
+
notation: simple
|
56
|
+
orientation: horizontal
|
57
|
+
polymorphism: false
|
58
|
+
sort: true
|
59
|
+
warn: true
|
60
|
+
title: sample title
|
61
|
+
exclude: null
|
62
|
+
only: null
|
63
|
+
prepend_primary: false
|
64
|
+
```
|
65
|
+
|
66
|
+
|
67
|
+
Learn more
|
68
|
+
----------
|
69
|
+
|
70
|
+
More information can be found on [Rails ERD's project homepage](http://voormedia.github.io/rails-erd/).
|
71
|
+
|
72
|
+
If you wish to extend or customise Rails ERD, take a look at the [API documentation](http://rubydoc.info/github/voormedia/rails-erd/frames).
|
73
|
+
|
74
|
+
|
75
|
+
About Rails ERD
|
76
|
+
---------------
|
77
|
+
|
78
|
+
Rails ERD was created by Rolf Timmermans (r.timmermans *at* voormedia.com)
|
79
|
+
|
80
|
+
Copyright 2010-2015 Voormedia - [www.voormedia.com](http://www.voormedia.com/)
|
81
|
+
|
82
|
+
|
83
|
+
License
|
84
|
+
-------
|
85
|
+
|
86
|
+
Rails ERD is released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "bundler"
|
2
|
+
require "rake/testtask"
|
3
|
+
require "yard"
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
Rake::TestTask.new do |test|
|
8
|
+
test.test_files = FileList["test/**/*_test.rb"]
|
9
|
+
end
|
10
|
+
|
11
|
+
YARD::Rake::YardocTask.new do |yard|
|
12
|
+
yard.files = ["lib/**/*.rb", "-", "LICENSE", "CHANGES.md"]
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Generate diagrams for bundled examples"
|
16
|
+
task :examples do
|
17
|
+
require File.expand_path("examples/generate", File.dirname(__FILE__))
|
18
|
+
end
|
19
|
+
|
20
|
+
task :default => :test
|
data/bin/erd
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Erd
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "Copy rails-erd rakefiles for automatic graphic generation"
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
# copy rake tasks
|
8
|
+
def copy_tasks
|
9
|
+
template "auto_generate_diagram.rake", "lib/tasks/auto_generate_diagram.rake"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# NOTE: only doing this in development as some production environments (Heroku)
|
2
|
+
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
|
3
|
+
# NOTE: to have a dev-mode tool do its thing in production.
|
4
|
+
if Rails.env.development?
|
5
|
+
Erd.load_tasks
|
6
|
+
end
|
data/lib/rails-erd.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "rails_erd"
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require "choice"
|
2
|
+
|
3
|
+
Choice.options do
|
4
|
+
separator ""
|
5
|
+
separator "Diagram options:"
|
6
|
+
|
7
|
+
option :title do
|
8
|
+
long "--title=TITLE"
|
9
|
+
desc "Replace default diagram title with a custom one."
|
10
|
+
end
|
11
|
+
|
12
|
+
option :notation do
|
13
|
+
long "--notation=STYLE"
|
14
|
+
desc "Diagram notation style, one of simple, bachman, uml or crowsfoot."
|
15
|
+
end
|
16
|
+
|
17
|
+
option :attributes do
|
18
|
+
long "--attributes=TYPE,..."
|
19
|
+
desc "Attribute groups to display: false, content, primary_keys, foreign_keys, timestamps and/or inheritance."
|
20
|
+
end
|
21
|
+
|
22
|
+
option :orientation do
|
23
|
+
long "--orientation=ORIENTATION"
|
24
|
+
desc "Orientation of diagram, either horizontal (default) or vertical."
|
25
|
+
end
|
26
|
+
|
27
|
+
option :inheritance do
|
28
|
+
long "--inheritance"
|
29
|
+
desc "Display (single table) inheritance relationships."
|
30
|
+
end
|
31
|
+
|
32
|
+
option :polymorphism do
|
33
|
+
long "--polymorphism"
|
34
|
+
desc "Display polymorphic and abstract entities."
|
35
|
+
end
|
36
|
+
|
37
|
+
option :no_indirect do
|
38
|
+
long "--direct"
|
39
|
+
desc "Omit indirect relationships (through other entities)."
|
40
|
+
end
|
41
|
+
|
42
|
+
option :no_disconnected do
|
43
|
+
long "--connected"
|
44
|
+
desc "Omit entities without relationships."
|
45
|
+
end
|
46
|
+
|
47
|
+
option :only do
|
48
|
+
long "--only"
|
49
|
+
desc "Filter to only include listed models in diagram."
|
50
|
+
end
|
51
|
+
|
52
|
+
option :exclude do
|
53
|
+
long "--exclude"
|
54
|
+
desc "Filter to exclude listed models in diagram."
|
55
|
+
end
|
56
|
+
|
57
|
+
option :sort do
|
58
|
+
long "--sort=BOOLEAN"
|
59
|
+
desc "Sort attribute list alphabetically"
|
60
|
+
end
|
61
|
+
|
62
|
+
option :prepend_primary do
|
63
|
+
long "--prepend_primary=BOOLEAN"
|
64
|
+
desc "Ensure primary key is at start of attribute list"
|
65
|
+
end
|
66
|
+
|
67
|
+
separator ""
|
68
|
+
separator "Output options:"
|
69
|
+
|
70
|
+
option :filename do
|
71
|
+
long "--filename=FILENAME"
|
72
|
+
desc "Basename of the output diagram."
|
73
|
+
end
|
74
|
+
|
75
|
+
option :filetype do
|
76
|
+
long "--filetype=TYPE"
|
77
|
+
desc "Output file type. Available types depend on the diagram renderer."
|
78
|
+
end
|
79
|
+
|
80
|
+
option :no_markup do
|
81
|
+
long "--no-markup"
|
82
|
+
desc "Disable markup for enhanced compatibility of .dot output with other applications."
|
83
|
+
end
|
84
|
+
|
85
|
+
option :open do
|
86
|
+
long "--open"
|
87
|
+
desc "Open the output file after it has been saved."
|
88
|
+
end
|
89
|
+
|
90
|
+
separator ""
|
91
|
+
separator "Common options:"
|
92
|
+
|
93
|
+
option :help do
|
94
|
+
long "--help"
|
95
|
+
desc "Display this help message."
|
96
|
+
end
|
97
|
+
|
98
|
+
option :debug do
|
99
|
+
long "--debug"
|
100
|
+
desc "Show stack traces when an error occurs."
|
101
|
+
end
|
102
|
+
|
103
|
+
option :version do
|
104
|
+
short "-v"
|
105
|
+
long "--version"
|
106
|
+
desc "Show version and quit."
|
107
|
+
action do
|
108
|
+
require "rails_erd/version"
|
109
|
+
$stderr.puts RailsERD::BANNER
|
110
|
+
exit
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
module RailsERD
|
116
|
+
class CLI
|
117
|
+
attr_reader :path, :options
|
118
|
+
|
119
|
+
class << self
|
120
|
+
def start
|
121
|
+
path = Choice.rest.first || Dir.pwd
|
122
|
+
options = Choice.choices.each_with_object({}) do |(key, value), opts|
|
123
|
+
if key.start_with? "no_"
|
124
|
+
opts[key.gsub("no_", "").to_sym] = !value
|
125
|
+
elsif value.to_s.include? ","
|
126
|
+
opts[key.to_sym] = value.split(",").map(&:to_s)
|
127
|
+
else
|
128
|
+
opts[key.to_sym] = value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
new(path, options).start
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def initialize(path, options)
|
136
|
+
@path, @options = path, options
|
137
|
+
require "rails_erd/diagram/graphviz"
|
138
|
+
end
|
139
|
+
|
140
|
+
def start
|
141
|
+
load_application
|
142
|
+
create_diagram
|
143
|
+
rescue Exception => e
|
144
|
+
$stderr.puts "Failed: #{e.class}: #{e.message}"
|
145
|
+
$stderr.puts e.backtrace.map { |t| " from #{t}" } if options[:debug]
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def load_application
|
151
|
+
$stderr.puts "Loading application in '#{File.basename(path)}'..."
|
152
|
+
# TODO: Add support for different kinds of environment.
|
153
|
+
require "#{path}/config/environment"
|
154
|
+
Rails.application.eager_load!
|
155
|
+
end
|
156
|
+
|
157
|
+
def create_diagram
|
158
|
+
$stderr.puts "Generating entity-relationship diagram for #{ActiveRecord::Base.descendants.length} models..."
|
159
|
+
file = RailsERD::Diagram::Graphviz.create(options)
|
160
|
+
$stderr.puts "Diagram saved to '#{file}'."
|
161
|
+
`open #{file}` if options[:open]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module RailsERD
|
4
|
+
class Config
|
5
|
+
USER_WIDE_CONFIG_FILE = File.expand_path(".erdconfig", ENV["HOME"])
|
6
|
+
CURRENT_CONFIG_FILE = File.expand_path(".erdconfig", Dir.pwd)
|
7
|
+
|
8
|
+
attr_reader :options
|
9
|
+
|
10
|
+
def self.load
|
11
|
+
new.load
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@options = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def load
|
19
|
+
load_file(USER_WIDE_CONFIG_FILE)
|
20
|
+
load_file(CURRENT_CONFIG_FILE)
|
21
|
+
|
22
|
+
@options
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.font_names_based_on_os
|
26
|
+
if use_os_x_fonts?
|
27
|
+
{ normal: "ArialMT",
|
28
|
+
bold: "Arial BoldMT",
|
29
|
+
italic: "Arial ItalicMT" }
|
30
|
+
else
|
31
|
+
{ normal: "Arial",
|
32
|
+
bold: "Arial Bold",
|
33
|
+
italic: "Arial Italic" }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def load_file(path)
|
40
|
+
if File.exists?(path)
|
41
|
+
YAML.load_file(path).each do |key, value|
|
42
|
+
key = key.to_sym
|
43
|
+
@options[key] = normalize_value(key, value)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def normalize_value(key, value)
|
49
|
+
case key
|
50
|
+
# <symbol>[,<symbol>,...] | false
|
51
|
+
when :attributes
|
52
|
+
if value == false
|
53
|
+
return value
|
54
|
+
else
|
55
|
+
# Comma separated string and strings in array are OK.
|
56
|
+
Array(value).join(",").split(",").map { |v| v.strip.to_sym }
|
57
|
+
end
|
58
|
+
|
59
|
+
# <symbol>
|
60
|
+
when :filetype, :notation, :orientation
|
61
|
+
value.to_sym
|
62
|
+
|
63
|
+
# [<string>]
|
64
|
+
when :only, :exclude
|
65
|
+
Array(value).join(",").split(",").map { |v| v.strip }
|
66
|
+
# true | false
|
67
|
+
when :disconnected, :indirect, :inheritance, :markup, :polymorphism, :warn
|
68
|
+
!!value
|
69
|
+
|
70
|
+
# nil | <string>
|
71
|
+
when :filename
|
72
|
+
value.nil? ? nil : value.to_s
|
73
|
+
|
74
|
+
# true | false | <string>
|
75
|
+
when :title
|
76
|
+
value.is_a?(String) ? value : !!value
|
77
|
+
|
78
|
+
else
|
79
|
+
value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.use_os_x_fonts?
|
84
|
+
host = RbConfig::CONFIG['host_os']
|
85
|
+
return true if host == "darwin"
|
86
|
+
|
87
|
+
if host.include? "darwin"
|
88
|
+
darwin_version_array = host.split("darwin").last.split(".").map(&:to_i)
|
89
|
+
|
90
|
+
return true if darwin_version_array[0] >= 13
|
91
|
+
return true if darwin_version_array[0] == 12 && darwin_version_array[1] >= 5
|
92
|
+
end
|
93
|
+
|
94
|
+
false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require "rails_erd/domain"
|
2
|
+
require "rails_erd/domain"
|
3
|
+
require "rails_erd"
|
4
|
+
require "rails_erd/domain/attribute"
|
5
|
+
require "rails_erd/domain/entity"
|
6
|
+
require "rails_erd/domain/relationship"
|
7
|
+
require "rails_erd/domain/specialization"
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
# monkeypatch to fix strange people with edges which causes segfault in graphviz
|
12
|
+
# https://github.com/voormedia/rails-erd/issues/70
|
13
|
+
module RailsERD
|
14
|
+
class Domain
|
15
|
+
class Relationship
|
16
|
+
class << self
|
17
|
+
private
|
18
|
+
|
19
|
+
def association_identity(association)
|
20
|
+
Set[association_owner(association), association_target(association)]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
module RailsERD
|
29
|
+
class Custom
|
30
|
+
attr_accessor :classes, :reflection_keys
|
31
|
+
|
32
|
+
#@class_name - Pass in the class name
|
33
|
+
#@name of the file
|
34
|
+
#@level - the depth you want to browse
|
35
|
+
def initialize( class_name, file_name, level=nil )
|
36
|
+
|
37
|
+
@file_name = file_name
|
38
|
+
@class_name = class_name
|
39
|
+
@classes = []
|
40
|
+
@classes << class_name
|
41
|
+
@level = level
|
42
|
+
process
|
43
|
+
generate
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate
|
48
|
+
puts "************************ classes length: #{@classes.length}"
|
49
|
+
options = {
|
50
|
+
:filename=>@file_name,
|
51
|
+
:filetype=>"pdf",
|
52
|
+
:attributes=>["foreign_keys", "primary_keys", "content"],
|
53
|
+
:only=>@classes
|
54
|
+
}
|
55
|
+
begin
|
56
|
+
byebug
|
57
|
+
file = RailsERD::Diagram::Graphviz.create(options)
|
58
|
+
rescue
|
59
|
+
puts "---------------------------------Graph viz creation error"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
def process
|
63
|
+
children_walk( @class_name.constantize.reflections, 0 )
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def children_walk( reflections, cur_level )
|
68
|
+
if @level == cur_level
|
69
|
+
return
|
70
|
+
end
|
71
|
+
keys = reflections.keys
|
72
|
+
for k in keys
|
73
|
+
p "***processing: #{k}"
|
74
|
+
ref = reflections[ k ]
|
75
|
+
class_name = ref.klass.name.to_s
|
76
|
+
p class_name
|
77
|
+
if !@classes.include? class_name
|
78
|
+
|
79
|
+
p "Adding #{class_name}"
|
80
|
+
@classes << class_name
|
81
|
+
|
82
|
+
begin
|
83
|
+
model = class_name.constantize
|
84
|
+
children_walk( model.reflections, cur_level + 1 )
|
85
|
+
rescue => e
|
86
|
+
warn "Cannot retrieve model: #{class_name}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def check_model_validity(model)
|
93
|
+
model.abstract_class? or model.table_exists? or raise "table #{model.table_name} does not exist"
|
94
|
+
rescue => e
|
95
|
+
warn "Ignoring invalid model #{model.name} (#{e.message})"
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|