rails-erd 0.1.0 → 0.1.1
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/.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"
|