rails-erd 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGES.rdoc +5 -0
- data/LICENSE +1 -1
- data/README.rdoc +140 -15
- data/Rakefile +5 -2
- data/VERSION +1 -1
- data/lib/rails_erd.rb +31 -15
- data/lib/rails_erd/attribute.rb +23 -1
- data/lib/rails_erd/diagram.rb +39 -14
- data/lib/rails_erd/domain.rb +2 -2
- data/lib/rails_erd/entity.rb +2 -2
- data/lib/rails_erd/relationship.rb +10 -7
- data/lib/rails_erd/relationship/cardinality.rb +1 -0
- data/test/test_helper.rb +2 -1
- data/test/unit/diagram_test.rb +34 -0
- metadata +8 -3
data/.gitignore
CHANGED
data/CHANGES.rdoc
CHANGED
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,28 +1,61 @@
|
|
1
1
|
= Rails ERD - Generate Entity-Relationship Diagrams for Rails applications
|
2
2
|
|
3
|
-
Rails ERD is a Rails plugin that allows you to easily generate
|
4
|
-
on your ActiveRecord models. The
|
3
|
+
Rails ERD is a Rails plugin that allows you to easily generate a diagram based
|
4
|
+
on your ActiveRecord models. The diagram gives an overview of how your
|
5
5
|
models are related. Having a diagram that describes your models is perfect
|
6
6
|
documentation for your application.
|
7
7
|
|
8
|
+
The second goal of Rails ERD is to provide you with a tool to inspect your
|
9
|
+
application's domain model. If you don't like the default output, it is very
|
10
|
+
easy to use the API to build your own diagrams.
|
11
|
+
|
8
12
|
Rails ERD was created specifically for Rails 3. It uses ActiveRecord reflection
|
9
|
-
to figure out how your models are associated.
|
13
|
+
to figure out how your models are associated. For older Rails applications,
|
14
|
+
you may want to try Railroad[http://railroad.rubyforge.org/].
|
15
|
+
|
16
|
+
== Links
|
17
|
+
|
18
|
+
Current documentation:
|
19
|
+
http://rails-erd.rubyforge.org/doc/
|
20
|
+
|
21
|
+
Source code at Github:
|
22
|
+
http://github.com/voormedia/rails-erd
|
23
|
+
|
24
|
+
Homepage:
|
25
|
+
http://rails-erd.rubyforge.org/
|
26
|
+
|
27
|
+
== Example output
|
28
|
+
|
29
|
+
This is an example diagram from an actual Rails application.
|
30
|
+
|
31
|
+
http://rails-erd.rubyforge.org/examples/event-forms.png
|
32
|
+
|
33
|
+
{Download generated PDF}[http://rails-erd.rubyforge.org/examples/event-forms.pdf]
|
34
|
+
|
35
|
+
Typo is a blogging application built in Rails. This is an excerpt from the
|
36
|
+
diagram that was generated from the Rails 3 branch (which is currently still
|
37
|
+
in development).
|
38
|
+
|
39
|
+
http://rails-erd.rubyforge.org/examples/typo-blog.png
|
40
|
+
|
41
|
+
{Download complete diagram as PDF}[http://rails-erd.rubyforge.org/examples/typo-blog.pdf]
|
42
|
+
|
10
43
|
|
11
44
|
== Getting started
|
12
45
|
|
13
46
|
In its most simple form, Rails ERD is a plugin for Rails 3 that provides you
|
14
47
|
with a Rake task to create an Entity-Relationship Diagram. It depends on the
|
15
|
-
Graphviz visualisation library.
|
16
|
-
|
17
|
-
|
48
|
+
Graphviz[http://www.graphviz.org/] visualisation library. In order to create
|
49
|
+
PDF files (the default), you should install or compile Graphviz with support
|
50
|
+
for Pango and Cairo.
|
18
51
|
|
19
|
-
For example, to install Graphviz with
|
52
|
+
For example, to install Graphviz with Homebrew:
|
20
53
|
|
21
|
-
%
|
54
|
+
% brew install cairo pango graphviz
|
22
55
|
|
23
|
-
Or with
|
56
|
+
Or with MacPorts:
|
24
57
|
|
25
|
-
%
|
58
|
+
% sudo port install graphviz
|
26
59
|
|
27
60
|
Next, install Rails ERD. Open your +Gemfile+, and add the following:
|
28
61
|
|
@@ -39,18 +72,110 @@ Entity-Relationship Diagram for your Rails application:
|
|
39
72
|
|
40
73
|
% rake erd
|
41
74
|
|
42
|
-
All done! You will now have a file named
|
75
|
+
All done! You will now have a file named <tt>ERD.pdf</tt> in your application root.
|
43
76
|
|
44
|
-
==
|
77
|
+
== Customisation
|
45
78
|
|
46
79
|
Rails ERD has several options that you can use to customise its behaviour.
|
47
80
|
All options can be provided on the command line. For example:
|
48
81
|
|
49
|
-
% rake erd exclude_timestamps=false
|
82
|
+
% rake erd orientation=vertical exclude_timestamps=false
|
83
|
+
|
84
|
+
exclude_foreign_keys:: Excludes foreign key columns from attribute lists.
|
85
|
+
Defaults to +true+.
|
86
|
+
exclude_primary_keys:: Excludes primary key columns from attribute lists.
|
87
|
+
Defaults to +true+.
|
88
|
+
exclude_timestamps:: Excludes timestamp columns (<tt>created_at/on</tt> and
|
89
|
+
<tt>updated_at/on</tt>) from attribute lists. Defaults
|
90
|
+
to +true+.
|
91
|
+
exclude_unconnected:: Excludes entities that are not connected to other
|
92
|
+
entities from the diagram. Defaults to +true+.
|
93
|
+
file_type:: The file type of the generated diagram. Defaults to +pdf+, which
|
94
|
+
is the recommended format. Other formats may render significantly
|
95
|
+
worse than a PDF file. The available formats depend on your installation
|
96
|
+
of Graphviz.
|
97
|
+
orientation:: The direction of the hierarchy of entities. Either +horizontal+
|
98
|
+
or +vertical+. Defaults to +horizontal+. The orientation of the
|
99
|
+
PDF that is generated depends on the amount of hierarchy
|
100
|
+
in your models.
|
101
|
+
suppress_warnings:: When set to +true+, no warnings are printed to the
|
102
|
+
command line while processing the domain model. Defaults
|
103
|
+
to +false+.
|
104
|
+
|
105
|
+
== Advanced use
|
106
|
+
|
107
|
+
Rails ERD also allows you to use its internal API to inspect your Rails domain
|
108
|
+
model. It is easy to generate alternative presentations of your Active Record
|
109
|
+
models this way. If used outside of Rails, install Rails ERD as a gem:
|
110
|
+
|
111
|
+
% gem install rails-erd
|
50
112
|
|
51
|
-
|
113
|
+
Suppose we have the following models:
|
114
|
+
|
115
|
+
class User < ActiveRecord::Base
|
116
|
+
has_many :posts
|
117
|
+
has_many :comments
|
118
|
+
end
|
119
|
+
|
120
|
+
class Post < ActiveRecord::Base
|
121
|
+
belongs_to :user
|
122
|
+
has_many :comments
|
123
|
+
end
|
124
|
+
|
125
|
+
class Comment < ActiveRecord::Base
|
126
|
+
belongs_to :user
|
127
|
+
belongs_to :post
|
128
|
+
end
|
129
|
+
|
130
|
+
Then you can inspect your domain model like this:
|
131
|
+
|
132
|
+
require "rails_erd/domain"
|
133
|
+
|
134
|
+
domain = RailsERD::Domain.generate
|
135
|
+
domain.entities
|
136
|
+
#=> [ #<RailsERD::Entity @model=Comment>,
|
137
|
+
# #<RailsERD::Entity @model=Post>,
|
138
|
+
# #<RailsERD::Entity @model=User> ]
|
139
|
+
|
140
|
+
domain.entities.first.connected?
|
141
|
+
#=> true
|
142
|
+
|
143
|
+
domain.relationships
|
144
|
+
#=> [ #<RailsERD::Relationship @source=Post @destination=Comment>,
|
145
|
+
# #<RailsERD::Relationship @source=User @destination=Comment>,
|
146
|
+
# #<RailsERD::Relationship @source=User @destination=Post> ]
|
147
|
+
|
148
|
+
domain.relationships.first.destination
|
149
|
+
#=> Comment
|
150
|
+
|
151
|
+
domain.relationships.first.mutual?
|
152
|
+
#=> true
|
153
|
+
|
154
|
+
domain.relationships.first.cardinality
|
155
|
+
#=> RailsERD::Relationship::Cardinality::OneToMany
|
156
|
+
|
157
|
+
The above is just a sample of what is possible. See the API documentation for
|
158
|
+
more details:
|
52
159
|
http://rails-erd.rubyforge.org/doc/
|
53
160
|
|
161
|
+
If you wish to generate your own graphs, take a look at how the default
|
162
|
+
diagrams are being generated. See the source of RailsERD::Diagram:
|
163
|
+
http://github.com/voormedia/rails-erd/blob/master/lib/rails_erd/diagram.rb
|
164
|
+
|
165
|
+
Please note that before the 1.0 release, the API may change subtly between
|
166
|
+
minor versions.
|
167
|
+
|
168
|
+
== About Rails ERD
|
169
|
+
|
170
|
+
Author: Rolf Timmermans (r.timmermans <i>at</i> voormedia.com)
|
171
|
+
|
172
|
+
Copyright 2010 Voormedia B.V.
|
173
|
+
|
54
174
|
== License
|
55
175
|
|
56
|
-
Rails ERD is released under the MIT license.
|
176
|
+
Rails ERD is released under the MIT license. See the LICENSE.
|
177
|
+
|
178
|
+
== Credits
|
179
|
+
|
180
|
+
Rails ERD depends on the Ruby-Graphviz library to generate diagrams:
|
181
|
+
http://github.com/glejeune/Ruby-Graphviz/
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ Jeweler::Tasks.new do |spec|
|
|
6
6
|
spec.name = "rails-erd"
|
7
7
|
spec.rubyforge_project = "rails-erd"
|
8
8
|
spec.summary = "Entity-relationship diagram for your Rails models."
|
9
|
-
spec.description = "Automatically generate an entity-relationship diagram (ERD) for
|
9
|
+
spec.description = "Automatically generate an entity-relationship diagram (ERD) for your Rails models."
|
10
10
|
|
11
11
|
spec.authors = ["Rolf Timmermans"]
|
12
12
|
spec.email = "r.timmermans@voormedia.com"
|
@@ -20,18 +20,21 @@ Jeweler::GemcutterTasks.new
|
|
20
20
|
|
21
21
|
Jeweler::RubyforgeTasks.new do |rubyforge|
|
22
22
|
rubyforge.doc_task = "rdoc"
|
23
|
+
rubyforge.remote_doc_path = "doc"
|
23
24
|
end
|
24
25
|
|
25
26
|
Rake::TestTask.new do |test|
|
26
27
|
test.pattern = "test/unit/**/*_test.rb"
|
27
28
|
end
|
28
29
|
|
30
|
+
task :default => :test
|
31
|
+
|
29
32
|
begin
|
30
33
|
require "hanna/rdoctask"
|
31
34
|
Rake::RDocTask.new do |rdoc|
|
32
35
|
rdoc.rdoc_files = Dir["[A-Z][A-Z]*"] + Dir["lib/**/*.rb"]
|
33
36
|
rdoc.title = "Rails ERD – Entity-Relationship Diagrams for Rails"
|
34
|
-
rdoc.rdoc_dir = "
|
37
|
+
rdoc.rdoc_dir = "rdoc"
|
35
38
|
end
|
36
39
|
rescue => e
|
37
40
|
puts e.message
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/lib/rails_erd.rb
CHANGED
@@ -5,21 +5,36 @@ require "rails_erd/railtie" if defined? Rails
|
|
5
5
|
# generation of the diagram and the domain model itself. Currently, the
|
6
6
|
# following options are supported:
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# exclude_foreign_keys:: Excludes foreign key columns from attribute lists.
|
9
|
+
# Defaults to +true+.
|
10
|
+
# exclude_primary_keys:: Excludes primary key columns from attribute lists.
|
11
|
+
# Defaults to +true+.
|
12
|
+
# exclude_timestamps:: Excludes timestamp columns (<tt>created_at/on</tt> and
|
13
|
+
# <tt>updated_at/on</tt>) from attribute lists. Defaults
|
14
|
+
# to +true+.
|
15
|
+
# exclude_unconnected:: Excludes entities that are not connected to other
|
16
|
+
# entities from the diagram. Defaults to +true+.
|
17
|
+
# file_type:: The file type of the generated diagram. Defaults to +:pdf+, which
|
18
|
+
# is the recommended format. Other formats may render significantly
|
19
|
+
# worse than a PDF file.
|
11
20
|
# orientation:: The direction of the hierarchy of entities. Either +:horizontal+
|
12
|
-
# or +:vertical+. Defaults to +:horizontal+.
|
21
|
+
# or +:vertical+. Defaults to +:horizontal+. The orientation of the
|
22
|
+
# PDF that is generated depends on the amount of hierarchy
|
23
|
+
# in your models.
|
13
24
|
# suppress_warnings:: When set to +true+, no warnings are printed to the
|
14
25
|
# command line while processing the domain model. Defaults
|
15
26
|
# to +false+.
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
27
|
+
#
|
28
|
+
# You can specify the option on the command line if you use Rails ERD with
|
29
|
+
# Rake:
|
30
|
+
#
|
31
|
+
# % rake erd orientation=vertical exclude_timestamps=false
|
32
|
+
#
|
33
|
+
# When using Rails ERD from within Ruby, you can set the options on the
|
34
|
+
# RailsERD namespace module:
|
35
|
+
#
|
36
|
+
# RailsERD.options.orientation = :vertical
|
37
|
+
# RailsERD.options.exclude_timestamps = false
|
23
38
|
module RailsERD
|
24
39
|
class << self
|
25
40
|
# Access to default options. Any instance of RailsERD::Domain and
|
@@ -28,11 +43,12 @@ module RailsERD
|
|
28
43
|
end
|
29
44
|
|
30
45
|
self.options = ActiveSupport::OrderedOptions[
|
31
|
-
:type, :pdf,
|
32
|
-
:orientation, :horizontal,
|
33
|
-
:exclude_timestamps, true,
|
34
|
-
:exclude_primary_keys, true,
|
35
46
|
:exclude_foreign_keys, true,
|
47
|
+
:exclude_primary_keys, true,
|
48
|
+
:exclude_timestamps, true,
|
49
|
+
:exclude_unconnected, true,
|
50
|
+
:file_type, :pdf,
|
51
|
+
:orientation, :horizontal,
|
36
52
|
:suppress_warnings, false
|
37
53
|
]
|
38
54
|
end
|
data/lib/rails_erd/attribute.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8
|
2
2
|
module RailsERD
|
3
|
+
# Describes an entity's attribute. Attributes correspond directly to
|
4
|
+
# database columns.
|
3
5
|
class Attribute
|
4
6
|
TIMESTAMP_NAMES = %w{created_at created_on updated_at updated_on} #:nodoc:
|
5
7
|
|
@@ -11,30 +13,42 @@ module RailsERD
|
|
11
13
|
|
12
14
|
attr_reader :column #:nodoc:
|
13
15
|
|
14
|
-
def initialize(domain, model, column)
|
16
|
+
def initialize(domain, model, column) #:nodoc:
|
15
17
|
@domain, @model, @column = domain, model, column
|
16
18
|
end
|
17
19
|
|
20
|
+
# The name of the attribute, equal to the column name.
|
18
21
|
def name
|
19
22
|
column.name
|
20
23
|
end
|
21
24
|
|
25
|
+
# The type of the attribute, equal to the Rails migration type. Can be any
|
26
|
+
# of +:string+, +:integer+, +:boolean+, +:text+, etc.
|
22
27
|
def type
|
23
28
|
column.type
|
24
29
|
end
|
25
30
|
|
31
|
+
# Returns +true+ if this attribute is mandatory. Mandatory attributes
|
32
|
+
# either have a presence validation (+validates_presence_of+), or have a
|
33
|
+
# <tt>NOT NULL</tt> database constraint.
|
26
34
|
def mandatory?
|
27
35
|
!column.null or @model.validators_on(name).map(&:kind).include?(:presence)
|
28
36
|
end
|
29
37
|
|
38
|
+
# Returns +true+ if this attribute is the primary key of the entity.
|
30
39
|
def primary_key?
|
31
40
|
@model.arel_table.primary_key == name
|
32
41
|
end
|
33
42
|
|
43
|
+
# Returns +true+ if this attribute is used as a foreign key for any
|
44
|
+
# relationship.
|
34
45
|
def foreign_key?
|
35
46
|
@domain.relationships_for(@model).map(&:associations).flatten.map(&:primary_key_name).include?(name)
|
36
47
|
end
|
37
48
|
|
49
|
+
# Returns +true+ if this attribute is one of the standard 'magic' Rails
|
50
|
+
# timestamp columns, being +created_at+, +updated_at+, +created_on+ or
|
51
|
+
# +updated_on+.
|
38
52
|
def timestamp?
|
39
53
|
TIMESTAMP_NAMES.include? name
|
40
54
|
end
|
@@ -51,6 +65,14 @@ module RailsERD
|
|
51
65
|
name
|
52
66
|
end
|
53
67
|
|
68
|
+
# Returns a short description of the attribute type. If the attribute has
|
69
|
+
# a non-standard limit or if it is mandatory, this information is included.
|
70
|
+
#
|
71
|
+
# Example output:
|
72
|
+
# <tt>:integer</tt>:: int
|
73
|
+
# <tt>:string, :limit => 255</tt>:: str
|
74
|
+
# <tt>:string, :limit => 128</tt>:: str (128)
|
75
|
+
# <tt>:boolean, :null => false</tt>:: bool *
|
54
76
|
def type_description
|
55
77
|
case type
|
56
78
|
when :integer then "int"
|
data/lib/rails_erd/diagram.rb
CHANGED
@@ -1,12 +1,23 @@
|
|
1
1
|
require "rails_erd/domain"
|
2
2
|
require "graphviz"
|
3
|
+
require "erb"
|
3
4
|
|
4
5
|
module RailsERD
|
6
|
+
# Create Graphviz-based diagrams based on the domain model. For easy
|
7
|
+
# command line graph generation, you can use rake:
|
8
|
+
#
|
9
|
+
# % rake erd
|
10
|
+
#
|
11
|
+
# Please see the README.rdoc file for more details on how to use Rails ERD
|
12
|
+
# from the command line.
|
5
13
|
class Diagram
|
6
14
|
NODE_LABEL_TEMPLATE = File.read(File.expand_path("templates/node.erb", File.dirname(__FILE__))) #:nodoc:
|
7
15
|
NODE_WIDTH = 130 #:nodoc:
|
8
16
|
|
9
17
|
class << self
|
18
|
+
# Generate a new domain model based on all <tt>ActiveRecord::Base</tt>
|
19
|
+
# subclasses, and create a new diagram. Use the given options for both
|
20
|
+
# the domain generation and the diagram generation.
|
10
21
|
def generate(options = {})
|
11
22
|
new(Domain.generate(options), options).output
|
12
23
|
end
|
@@ -14,10 +25,24 @@ module RailsERD
|
|
14
25
|
|
15
26
|
attr_reader :options #:nodoc:
|
16
27
|
|
28
|
+
# Create a new diagram based on the given domain.
|
17
29
|
def initialize(domain, options = {})
|
18
30
|
@domain, @options = domain, RailsERD.options.merge(options)
|
19
31
|
end
|
20
32
|
|
33
|
+
# Save the diagram.
|
34
|
+
def output
|
35
|
+
graph.output(options.file_type.to_sym => file_name)
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the file name that will be used when saving the diagram.
|
40
|
+
def file_name
|
41
|
+
"ERD.#{options.file_type}"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
21
46
|
def graph
|
22
47
|
@graph ||= GraphViz.new(@domain.name, :type => :digraph) do |graph|
|
23
48
|
graph[:rankdir] = horizontal? ? :LR : :TB
|
@@ -44,16 +69,23 @@ module RailsERD
|
|
44
69
|
|
45
70
|
nodes = {}
|
46
71
|
|
47
|
-
@domain.entities.
|
72
|
+
@domain.entities.each do |entity|
|
73
|
+
if options.exclude_unconnected && !entity.connected?
|
74
|
+
warn "Skipping unconnected model #{entity.name} (use exclude_unconnected=false to include)"
|
75
|
+
next
|
76
|
+
end
|
77
|
+
|
48
78
|
attributes = entity.attributes.reject { |attribute|
|
49
79
|
options.exclude_primary_keys && attribute.primary_key? or
|
50
80
|
options.exclude_foreign_keys && attribute.foreign_key? or
|
51
81
|
options.exclude_timestamps && attribute.timestamp?
|
52
82
|
}
|
53
83
|
|
54
|
-
nodes[entity] = graph.add_node entity.name, :
|
84
|
+
nodes[entity] = graph.add_node entity.name, :label => "<" + ERB.new(NODE_LABEL_TEMPLATE, nil, "<>").result(binding) + ">"
|
55
85
|
end
|
56
|
-
|
86
|
+
|
87
|
+
raise "No (connected) entities found; create your models first!" if nodes.empty?
|
88
|
+
|
57
89
|
@domain.relationships.each do |relationship|
|
58
90
|
options = {}
|
59
91
|
options[:arrowhead] = relationship.cardinality.one_to_one? ? :dot : :normal
|
@@ -66,17 +98,6 @@ module RailsERD
|
|
66
98
|
end
|
67
99
|
end
|
68
100
|
|
69
|
-
def output
|
70
|
-
graph.output(options.type.to_sym => file_name)
|
71
|
-
self
|
72
|
-
end
|
73
|
-
|
74
|
-
def file_name
|
75
|
-
"ERD.#{options.type}"
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
101
|
def horizontal?
|
81
102
|
options.orientation == :horizontal
|
82
103
|
end
|
@@ -84,5 +105,9 @@ module RailsERD
|
|
84
105
|
def vertical?
|
85
106
|
!horizontal?
|
86
107
|
end
|
108
|
+
|
109
|
+
def warn(message)
|
110
|
+
puts "Warning: #{message}" unless options.suppress_warnings
|
111
|
+
end
|
87
112
|
end
|
88
113
|
end
|
data/lib/rails_erd/domain.rb
CHANGED
@@ -45,12 +45,12 @@ module RailsERD
|
|
45
45
|
@relationships ||= Relationship.from_associations(self, associations)
|
46
46
|
end
|
47
47
|
|
48
|
-
# Returns a specific entity object for the given
|
48
|
+
# Returns a specific entity object for the given Active Record model.
|
49
49
|
def entity_for(model) #:nodoc:
|
50
50
|
entity_mapping[model] or raise "model #{model} exists, but is not included in the domain"
|
51
51
|
end
|
52
52
|
|
53
|
-
# Returns an array of relationships for the given
|
53
|
+
# Returns an array of relationships for the given Active Record model.
|
54
54
|
def relationships_for(model) #:nodoc:
|
55
55
|
relationships_mapping[model] or []
|
56
56
|
end
|
data/lib/rails_erd/entity.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module RailsERD
|
2
|
-
# Entities represent your
|
2
|
+
# Entities represent your Active Record models. Entities may be connected
|
3
3
|
# to other entities.
|
4
4
|
class Entity
|
5
5
|
# The domain in which this entity resides.
|
6
6
|
attr_reader :domain
|
7
7
|
|
8
|
-
# The
|
8
|
+
# The Active Record model that this entity corresponds to.
|
9
9
|
attr_reader :model
|
10
10
|
|
11
11
|
def initialize(domain, model) #:nodoc:
|
@@ -1,4 +1,8 @@
|
|
1
1
|
module RailsERD
|
2
|
+
# Describes a relationship between two entities. A relationship is detected
|
3
|
+
# based on Active Record associations. One relationship may represent more
|
4
|
+
# than one association, however. Associations that share the same foreign
|
5
|
+
# key are grouped together.
|
2
6
|
class Relationship
|
3
7
|
class << self
|
4
8
|
def from_associations(domain, associations) #:nodoc:
|
@@ -14,16 +18,15 @@ module RailsERD
|
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
|
-
#
|
21
|
+
# The domain in which this relationship is defined.
|
18
22
|
attr_reader :domain
|
19
23
|
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# model.
|
24
|
+
# The source entity. It corresponds to the model that has defined a
|
25
|
+
# +has_one+ or +has_many+ association with the other model.
|
23
26
|
attr_reader :source
|
24
27
|
|
25
|
-
#
|
26
|
-
#
|
28
|
+
# The destination entity. It corresponds to the model that has defined
|
29
|
+
# a +belongs_to+ association with the other model.
|
27
30
|
attr_reader :destination
|
28
31
|
|
29
32
|
def initialize(domain, associations) #:nodoc:
|
@@ -35,7 +38,7 @@ module RailsERD
|
|
35
38
|
@source, @destination = @destination, @source if assoc.belongs_to?
|
36
39
|
end
|
37
40
|
|
38
|
-
# Returns all
|
41
|
+
# Returns all Active Record association objects that describe this
|
39
42
|
# relationship.
|
40
43
|
def associations
|
41
44
|
@forward_associations + @reverse_associations
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "rubygems"
|
1
2
|
require "test/unit"
|
2
3
|
require "active_support/test_case"
|
3
4
|
|
@@ -66,7 +67,7 @@ class ActiveSupport::TestCase
|
|
66
67
|
ActiveRecord::Base.connection.drop_table table
|
67
68
|
end
|
68
69
|
ActiveRecord::Base.direct_descendants.clear
|
69
|
-
Arel::Relation.class_variable_set :@@connection_tables_primary_keys, {}
|
70
|
+
Arel::Relation.send :class_variable_set, :@@connection_tables_primary_keys, {}
|
70
71
|
ActiveSupport::Dependencies::Reference.clear!
|
71
72
|
end
|
72
73
|
end
|
data/test/unit/diagram_test.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require "rails_erd/diagram"
|
4
|
+
|
5
|
+
class DiagramTest < ActiveSupport::TestCase
|
6
|
+
def teardown
|
7
|
+
FileUtils.rm "ERD.dot" rescue nil
|
8
|
+
end
|
9
|
+
|
10
|
+
# Diagram generation =======================================================
|
11
|
+
test "generate should create output based on domain model" do
|
12
|
+
create_model "Foo", :bar => :references do
|
13
|
+
belongs_to :bar
|
14
|
+
end
|
15
|
+
create_model "Bar"
|
16
|
+
RailsERD::Diagram.generate(:file_type => :dot)
|
17
|
+
assert File.exists?("ERD.dot")
|
18
|
+
end
|
19
|
+
|
20
|
+
test "generate should not create output if there are no connected models" do
|
21
|
+
RailsERD::Diagram.generate(:file_type => :dot) rescue nil
|
22
|
+
assert !File.exists?("ERD.dot")
|
23
|
+
end
|
24
|
+
|
25
|
+
test "generate should abort and complain if there are no connected models" do
|
26
|
+
message = nil
|
27
|
+
begin
|
28
|
+
RailsERD::Diagram.generate(:file_type => :dot)
|
29
|
+
rescue => e
|
30
|
+
message = e.message
|
31
|
+
end
|
32
|
+
assert_match /No \(connected\) entities found/, message
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-erd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Rolf Timmermans
|
@@ -25,6 +26,7 @@ dependencies:
|
|
25
26
|
requirements:
|
26
27
|
- - ~>
|
27
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
28
30
|
segments:
|
29
31
|
- 3
|
30
32
|
- 0
|
@@ -40,6 +42,7 @@ dependencies:
|
|
40
42
|
requirements:
|
41
43
|
- - ~>
|
42
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 25
|
43
46
|
segments:
|
44
47
|
- 0
|
45
48
|
- 9
|
@@ -47,7 +50,7 @@ dependencies:
|
|
47
50
|
version: 0.9.17
|
48
51
|
type: :runtime
|
49
52
|
version_requirements: *id002
|
50
|
-
description: Automatically generate an entity-relationship diagram (ERD) for
|
53
|
+
description: Automatically generate an entity-relationship diagram (ERD) for your Rails models.
|
51
54
|
email: r.timmermans@voormedia.com
|
52
55
|
executables: []
|
53
56
|
|
@@ -95,6 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
98
|
requirements:
|
96
99
|
- - ">="
|
97
100
|
- !ruby/object:Gem::Version
|
101
|
+
hash: 3
|
98
102
|
segments:
|
99
103
|
- 0
|
100
104
|
version: "0"
|
@@ -103,6 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
107
|
requirements:
|
104
108
|
- - ">="
|
105
109
|
- !ruby/object:Gem::Version
|
110
|
+
hash: 3
|
106
111
|
segments:
|
107
112
|
- 0
|
108
113
|
version: "0"
|