rails-erd 0.4.5 → 1.0.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.
- data/CHANGES.rdoc +18 -0
- data/LICENSE +1 -1
- data/README.md +3 -3
- data/Rakefile +57 -46
- data/bin/erd +4 -0
- data/lib/rails_erd.rb +4 -2
- data/lib/rails_erd/cli.rb +149 -0
- data/lib/rails_erd/diagram.rb +18 -16
- data/lib/rails_erd/diagram/graphviz.rb +23 -2
- data/lib/rails_erd/domain/attribute.rb +9 -3
- data/lib/rails_erd/domain/entity.rb +15 -15
- data/lib/rails_erd/domain/relationship.rb +11 -1
- data/lib/rails_erd/domain/relationship/cardinality.rb +15 -15
- data/lib/rails_erd/domain/specialization.rb +8 -8
- data/lib/rails_erd/version.rb +4 -0
- data/test/test_helper.rb +14 -11
- data/test/unit/attribute_test.rb +66 -3
- data/test/unit/cardinality_test.rb +10 -10
- data/test/unit/diagram_test.rb +44 -18
- data/test/unit/domain_test.rb +20 -20
- data/test/unit/entity_test.rb +19 -19
- data/test/unit/graphviz_test.rb +53 -10
- data/test/unit/rake_task_test.rb +8 -8
- data/test/unit/relationship_test.rb +31 -31
- data/test/unit/specialization_test.rb +3 -3
- metadata +72 -108
- data/.gemtest +0 -0
- data/Gemfile +0 -19
- data/Gemfile.lock +0 -44
- data/VERSION +0 -1
- data/rails-erd.gemspec +0 -105
data/CHANGES.rdoc
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
=== 1.0.0:
|
2
|
+
|
3
|
+
* The internal API is now stable and will be backwards compatible until
|
4
|
+
the next major version.
|
5
|
+
* Added experimental command line interface (erd). The CLI still requires a
|
6
|
+
Rails application to be present, but it may one day support other kinds of
|
7
|
+
applications.
|
8
|
+
* Crow's foot notation (also known as the Information Engineering notation)
|
9
|
+
can be used by adding 'notation=crowsfoot' to the 'rake erd' command
|
10
|
+
(contributed by Jeremy Holland).
|
11
|
+
* Filter models by using the only or exclude options (only=ModelOne,ModelTwo
|
12
|
+
or exclude=ModelThree,ModelFour) from the command line (contributed by
|
13
|
+
Milovan Zogovic).
|
14
|
+
* Process column types that are unsupported by Rails (contributed by Erik
|
15
|
+
Gustavson).
|
16
|
+
* Ignore custom limit/scale attributes that cannot be converted to an integer
|
17
|
+
(reported by Adam St. John).
|
18
|
+
|
1
19
|
=== 0.4.5:
|
2
20
|
|
3
21
|
* Display more helpful error message when the application models could not be
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -31,11 +31,11 @@ Getting started
|
|
31
31
|
See the [installation instructions](http://rails-erd.rubyforge.org/install.html)
|
32
32
|
for a complete description of how to install Rails ERD. Here's a summary:
|
33
33
|
|
34
|
-
* Install Graphviz 2.22+
|
34
|
+
* Install Graphviz 2.22+ ([how?](http://rails-erd.rubyforge.org/install.html))
|
35
35
|
|
36
36
|
* Add <tt>gem "rails-erd"</tt> to your application's Gemfile
|
37
37
|
|
38
|
-
* Run <tt>
|
38
|
+
* Run <tt>bundle exec erd</tt>
|
39
39
|
|
40
40
|
|
41
41
|
Learn more
|
@@ -51,7 +51,7 @@ About Rails ERD
|
|
51
51
|
|
52
52
|
Rails ERD was created by Rolf Timmermans (r.timmermans *at* voormedia.com)
|
53
53
|
|
54
|
-
Copyright 2010-
|
54
|
+
Copyright 2010-2012 Voormedia - [www.voormedia.com](http://www.voormedia.com/)
|
55
55
|
|
56
56
|
|
57
57
|
License
|
data/Rakefile
CHANGED
@@ -1,54 +1,65 @@
|
|
1
|
-
|
2
|
-
require "jeweler"
|
1
|
+
require "bundler"
|
3
2
|
require "rake/testtask"
|
4
3
|
|
5
|
-
|
6
|
-
spec.name = "rails-erd"
|
7
|
-
spec.rubyforge_project = "rails-erd"
|
8
|
-
spec.summary = "Entity-relationship diagram for your Rails models."
|
9
|
-
spec.description = "Automatically generate an entity-relationship diagram (ERD) for your Rails models."
|
10
|
-
|
11
|
-
spec.authors = ["Rolf Timmermans"]
|
12
|
-
spec.email = "r.timmermans@voormedia.com"
|
13
|
-
spec.homepage = "http://rails-erd.rubyforge.org/"
|
14
|
-
|
15
|
-
# Don't bundle examples or website in gem.
|
16
|
-
excluded = Dir["{examples,site}/**/*"]
|
17
|
-
spec.files -= excluded
|
18
|
-
spec.test_files -= excluded
|
19
|
-
end
|
20
|
-
|
21
|
-
Jeweler::GemcutterTasks.new
|
22
|
-
|
23
|
-
Jeweler::RubyforgeTasks.new do |rubyforge|
|
24
|
-
rubyforge.doc_task = "rdoc"
|
25
|
-
rubyforge.remote_doc_path = "doc"
|
26
|
-
end
|
4
|
+
Bundler::GemHelper.install_tasks
|
27
5
|
|
28
6
|
Rake::TestTask.new do |test|
|
29
|
-
test.
|
7
|
+
test.test_files = FileList["test/**/*_test.rb"]
|
30
8
|
end
|
31
9
|
|
32
10
|
task :default => :test
|
33
11
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
12
|
+
# # encoding: utf-8
|
13
|
+
# require "jeweler"
|
14
|
+
# require "rake/testtask"
|
15
|
+
#
|
16
|
+
# Jeweler::Tasks.new do |spec|
|
17
|
+
# spec.name = "rails-erd"
|
18
|
+
# spec.rubyforge_project = "rails-erd"
|
19
|
+
# spec.summary = "Entity-relationship diagram for your Rails models."
|
20
|
+
# spec.description = "Automatically generate an entity-relationship diagram (ERD) for your Rails models."
|
21
|
+
#
|
22
|
+
# spec.authors = ["Rolf Timmermans"]
|
23
|
+
# spec.email = "r.timmermans@voormedia.com"
|
24
|
+
# spec.homepage = "http://rails-erd.rubyforge.org/"
|
25
|
+
#
|
26
|
+
# # Don't bundle examples or website in gem.
|
27
|
+
# excluded = Dir["{examples,site}/**/*"]
|
28
|
+
# spec.files -= excluded
|
29
|
+
# spec.test_files -= excluded
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# Jeweler::GemcutterTasks.new
|
33
|
+
#
|
34
|
+
# Jeweler::RubyforgeTasks.new do |rubyforge|
|
35
|
+
# rubyforge.doc_task = "rdoc"
|
36
|
+
# rubyforge.remote_doc_path = "doc"
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# Rake::TestTask.new do |test|
|
40
|
+
# test.pattern = "test/unit/**/*_test.rb"
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# task :default => :test
|
44
|
+
#
|
45
|
+
# begin
|
46
|
+
# require "hanna/rdoctask"
|
47
|
+
# Rake::RDocTask.new do |rdoc|
|
48
|
+
# rdoc.rdoc_files = %w{CHANGES.rdoc LICENSE} + Dir["lib/**/*.rb"]
|
49
|
+
# rdoc.title = "Rails ERD – API Documentation"
|
50
|
+
# rdoc.rdoc_dir = "rdoc"
|
51
|
+
# rdoc.main = "RailsERD"
|
52
|
+
# end
|
53
|
+
# rescue LoadError
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# desc "Generate diagrams for bundled examples"
|
57
|
+
# task :examples do
|
58
|
+
# require File.expand_path("examples/generate", File.dirname(__FILE__))
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# namespace :examples do
|
62
|
+
# task :sfdp do
|
63
|
+
# require File.expand_path("examples/sfdp", File.dirname(__FILE__))
|
64
|
+
# end
|
65
|
+
# end
|
data/bin/erd
ADDED
data/lib/rails_erd.rb
CHANGED
@@ -50,7 +50,7 @@ module RailsERD
|
|
50
50
|
self.options = ActiveSupport::OrderedOptions[
|
51
51
|
:attributes, :content,
|
52
52
|
:disconnected, true,
|
53
|
-
:filename, "
|
53
|
+
:filename, "erd",
|
54
54
|
:filetype, :pdf,
|
55
55
|
:indirect, true,
|
56
56
|
:inheritance, false,
|
@@ -59,6 +59,8 @@ module RailsERD
|
|
59
59
|
:orientation, :horizontal,
|
60
60
|
:polymorphism, false,
|
61
61
|
:warn, true,
|
62
|
-
:title, true
|
62
|
+
:title, true,
|
63
|
+
:exclude, nil,
|
64
|
+
:only, nil
|
63
65
|
]
|
64
66
|
end
|
@@ -0,0 +1,149 @@
|
|
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
|
+
default "simple"
|
16
|
+
end
|
17
|
+
|
18
|
+
option :attributes do
|
19
|
+
long "--attributes=TYPE,..."
|
20
|
+
desc "Attribute groups to display: content, primary_keys, foreign_keys, timestamps and/or inheritance."
|
21
|
+
default "content"
|
22
|
+
end
|
23
|
+
|
24
|
+
option :orientation do
|
25
|
+
long "--orientation=ORIENTATION"
|
26
|
+
desc "Orientation of diagram, either horizontal (default) or vertical."
|
27
|
+
default "orientation"
|
28
|
+
end
|
29
|
+
|
30
|
+
option :inheritance do
|
31
|
+
long "--inheritance"
|
32
|
+
desc "Display (single table) inheritance relationships."
|
33
|
+
end
|
34
|
+
|
35
|
+
option :polymorphism do
|
36
|
+
long "--polymorphism"
|
37
|
+
desc "Display polymorphic relationships."
|
38
|
+
end
|
39
|
+
|
40
|
+
option :no_indirect do
|
41
|
+
long "--direct"
|
42
|
+
desc "Omit indirect relationships (through other entities)."
|
43
|
+
end
|
44
|
+
|
45
|
+
option :no_disconnected do
|
46
|
+
long "--connected"
|
47
|
+
desc "Omit entities without relationships."
|
48
|
+
end
|
49
|
+
|
50
|
+
separator ""
|
51
|
+
separator "Output options:"
|
52
|
+
|
53
|
+
option :filename do
|
54
|
+
long "--filename=FILENAME"
|
55
|
+
desc "Basename of the output diagram."
|
56
|
+
default "erd"
|
57
|
+
end
|
58
|
+
|
59
|
+
option :filetype do
|
60
|
+
long "--filetype=TYPE"
|
61
|
+
desc "Output file type. Available types depend on the diagram renderer."
|
62
|
+
default "pdf"
|
63
|
+
end
|
64
|
+
|
65
|
+
option :no_markup do
|
66
|
+
long "--no-markup"
|
67
|
+
desc "Disable markup for enhanced compatibility of .dot output with other applications."
|
68
|
+
end
|
69
|
+
|
70
|
+
option :open do
|
71
|
+
long "--open"
|
72
|
+
desc "Open the output file after it has been saved."
|
73
|
+
end
|
74
|
+
|
75
|
+
separator ""
|
76
|
+
separator "Common options:"
|
77
|
+
|
78
|
+
option :help do
|
79
|
+
long "--help"
|
80
|
+
desc "Display this help message."
|
81
|
+
end
|
82
|
+
|
83
|
+
option :debug do
|
84
|
+
long "--debug"
|
85
|
+
desc "Show stack traces when an error occurs."
|
86
|
+
end
|
87
|
+
|
88
|
+
option :version do
|
89
|
+
short "-v"
|
90
|
+
long "--version"
|
91
|
+
desc "Show version and quit."
|
92
|
+
action do
|
93
|
+
require "rails_erd/version"
|
94
|
+
$stderr.puts RailsERD::BANNER
|
95
|
+
exit
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
module RailsERD
|
101
|
+
class CLI
|
102
|
+
attr_reader :path, :options
|
103
|
+
|
104
|
+
class << self
|
105
|
+
def start
|
106
|
+
path = Choice.rest.first || Dir.pwd
|
107
|
+
options = Choice.choices.each_with_object({}) do |(key, value), opts|
|
108
|
+
if key.start_with? "no_"
|
109
|
+
opts[key.gsub("no_", "").to_sym] = !value
|
110
|
+
elsif value.to_s.include? ","
|
111
|
+
opts[key.to_sym] = value.split(",").map(&:to_sym)
|
112
|
+
else
|
113
|
+
opts[key.to_sym] = value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
new(path, options).start
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def initialize(path, options)
|
121
|
+
@path, @options = path, options
|
122
|
+
require "rails_erd/diagram/graphviz"
|
123
|
+
end
|
124
|
+
|
125
|
+
def start
|
126
|
+
load_application
|
127
|
+
create_diagram
|
128
|
+
rescue Exception => e
|
129
|
+
$stderr.puts "Failed: #{e.class}: #{e.message}"
|
130
|
+
$stderr.puts e.backtrace.map { |t| " from #{t}" } if options[:debug]
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def load_application
|
136
|
+
$stderr.puts "Loading application in '#{File.basename(path)}'..."
|
137
|
+
# TODO: Add support for different kinds of environment.
|
138
|
+
require "#{path}/config/environment"
|
139
|
+
Rails.application.eager_load!
|
140
|
+
end
|
141
|
+
|
142
|
+
def create_diagram
|
143
|
+
$stderr.puts "Generating entity-relationship diagram for #{ActiveRecord::Base.descendants.length} models..."
|
144
|
+
file = RailsERD::Diagram::Graphviz.create(options)
|
145
|
+
$stderr.puts "Diagram saved to '#{file}'."
|
146
|
+
`open #{file}` if options[:open]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/rails_erd/diagram.rb
CHANGED
@@ -3,7 +3,7 @@ require "rails_erd/domain"
|
|
3
3
|
module RailsERD
|
4
4
|
# This class is an abstract class that will process a domain model and
|
5
5
|
# allows easy creation of diagrams. To implement a new diagram type, derive
|
6
|
-
# from this class and override +process_entity+, +process_relationship+,
|
6
|
+
# from this class and override +process_entity+, +process_relationship+,
|
7
7
|
# and (optionally) +save+.
|
8
8
|
#
|
9
9
|
# As an example, a diagram class that generates code that can be used with
|
@@ -73,13 +73,13 @@ module RailsERD
|
|
73
73
|
def create(options = {})
|
74
74
|
new(Domain.generate(options), options).create
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
protected
|
78
|
-
|
78
|
+
|
79
79
|
def setup(&block)
|
80
80
|
callbacks[:setup] = block
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
def each_entity(&block)
|
84
84
|
callbacks[:each_entity] = block
|
85
85
|
end
|
@@ -91,7 +91,7 @@ module RailsERD
|
|
91
91
|
def each_specialization(&block)
|
92
92
|
callbacks[:each_specialization] = block
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
def save(&block)
|
96
96
|
callbacks[:save] = block
|
97
97
|
end
|
@@ -105,7 +105,7 @@ module RailsERD
|
|
105
105
|
|
106
106
|
# The options that are used to create this diagram.
|
107
107
|
attr_reader :options
|
108
|
-
|
108
|
+
|
109
109
|
# The domain that this diagram represents.
|
110
110
|
attr_reader :domain
|
111
111
|
|
@@ -113,13 +113,13 @@ module RailsERD
|
|
113
113
|
def initialize(domain, options = {})
|
114
114
|
@domain, @options = domain, RailsERD.options.merge(options)
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
# Generates and saves the diagram, returning the result of +save+.
|
118
118
|
def create
|
119
119
|
generate
|
120
120
|
save
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
# Generates the diagram, but does not save the output. It is called
|
124
124
|
# internally by Diagram#create.
|
125
125
|
def generate
|
@@ -137,19 +137,21 @@ module RailsERD
|
|
137
137
|
instance_exec relationship, &callbacks[:each_relationship]
|
138
138
|
end
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
def save
|
142
142
|
instance_eval &callbacks[:save]
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
private
|
146
|
-
|
146
|
+
|
147
147
|
def callbacks
|
148
148
|
@callbacks ||= self.class.send(:callbacks)
|
149
149
|
end
|
150
|
-
|
150
|
+
|
151
151
|
def filtered_entities
|
152
152
|
@domain.entities.reject { |entity|
|
153
|
+
options.exclude && entity.model && [options.exclude].flatten.include?(entity.name.to_sym) or
|
154
|
+
options.only && entity.model && ![options.only].flatten.include?(entity.name.to_sym) or
|
153
155
|
!options.inheritance && entity.specialized? or
|
154
156
|
!options.polymorphism && entity.generalized? or
|
155
157
|
!options.disconnected && entity.disconnected?
|
@@ -157,20 +159,20 @@ module RailsERD
|
|
157
159
|
raise "No entities found; create your models first!" if entities.empty?
|
158
160
|
end
|
159
161
|
end
|
160
|
-
|
162
|
+
|
161
163
|
def filtered_relationships
|
162
164
|
@domain.relationships.reject { |relationship|
|
163
165
|
!options.indirect && relationship.indirect?
|
164
166
|
}
|
165
167
|
end
|
166
|
-
|
168
|
+
|
167
169
|
def filtered_specializations
|
168
170
|
@domain.specializations.reject { |specialization|
|
169
171
|
!options.inheritance && specialization.inheritance? or
|
170
172
|
!options.polymorphism && specialization.polymorphic?
|
171
173
|
}
|
172
174
|
end
|
173
|
-
|
175
|
+
|
174
176
|
def filtered_attributes(entity)
|
175
177
|
entity.attributes.reject { |attribute|
|
176
178
|
# Select attributes that satisfy the conditions in the :attributes option.
|
@@ -178,7 +180,7 @@ module RailsERD
|
|
178
180
|
[*options.attributes].none? { |type| attribute.send(:"#{type.to_s.chomp('s')}?") }
|
179
181
|
}
|
180
182
|
end
|
181
|
-
|
183
|
+
|
182
184
|
def warn(message)
|
183
185
|
puts "Warning: #{message}" if options.warn
|
184
186
|
end
|