jw-rails-erd 1.4.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/voormedia/rails-erd.svg?branch=master)](https://travis-ci.org/voormedia/rails-erd) [![Code Climate](https://codeclimate.com/github/voormedia/rails-erd/badges/gpa.svg)](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
|
+
![Entity-Relationship Diagram](http://voormedia.github.io/rails-erd/images/entity-relationship-diagram.png)
|
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
|