rails-erd 1.0.0 → 1.1.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/LICENSE +1 -1
- data/README.md +1 -1
- data/Rakefile +10 -55
- data/lib/rails_erd/cli.rb +11 -1
- data/lib/rails_erd/diagram/graphviz.rb +9 -7
- data/lib/rails_erd/domain.rb +2 -2
- data/lib/rails_erd/domain/entity.rb +7 -5
- data/lib/rails_erd/domain/relationship/cardinality.rb +1 -1
- data/lib/rails_erd/domain/specialization.rb +19 -7
- data/lib/rails_erd/version.rb +1 -1
- data/test/test_helper.rb +12 -4
- data/test/unit/diagram_test.rb +10 -6
- data/test/unit/domain_test.rb +17 -34
- data/test/unit/entity_test.rb +39 -44
- data/test/unit/graphviz_test.rb +38 -3
- data/test/unit/specialization_test.rb +12 -2
- metadata +30 -21
- data/CHANGES.rdoc +0 -94
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -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-2013 Voormedia - [www.voormedia.com](http://www.voormedia.com/)
|
55
55
|
|
56
56
|
|
57
57
|
License
|
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "bundler"
|
2
2
|
require "rake/testtask"
|
3
|
+
require "yard"
|
3
4
|
|
4
5
|
Bundler::GemHelper.install_tasks
|
5
6
|
|
@@ -7,59 +8,13 @@ Rake::TestTask.new do |test|
|
|
7
8
|
test.test_files = FileList["test/**/*_test.rb"]
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
+
YARD::Rake::YardocTask.new do |yard|
|
12
|
+
yard.files = ["lib/**/*.rb", "-", "LICENSE", "CHANGES.md"]
|
13
|
+
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
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/lib/rails_erd/cli.rb
CHANGED
@@ -34,7 +34,7 @@ Choice.options do
|
|
34
34
|
|
35
35
|
option :polymorphism do
|
36
36
|
long "--polymorphism"
|
37
|
-
desc "Display polymorphic
|
37
|
+
desc "Display polymorphic and abstract entities."
|
38
38
|
end
|
39
39
|
|
40
40
|
option :no_indirect do
|
@@ -47,6 +47,16 @@ Choice.options do
|
|
47
47
|
desc "Omit entities without relationships."
|
48
48
|
end
|
49
49
|
|
50
|
+
option :only do
|
51
|
+
long "--only"
|
52
|
+
desc "Filter to only include listed models in diagram."
|
53
|
+
end
|
54
|
+
|
55
|
+
option :exclude do
|
56
|
+
long "--exclude"
|
57
|
+
desc "Filter to exclude listed models in diagram."
|
58
|
+
end
|
59
|
+
|
50
60
|
separator ""
|
51
61
|
separator "Output options:"
|
52
62
|
|
@@ -5,7 +5,7 @@ require "erb"
|
|
5
5
|
|
6
6
|
# Fix bad RegEx test in Ruby-Graphviz.
|
7
7
|
GraphViz::Types::LblString.class_eval do
|
8
|
-
def output
|
8
|
+
def output # @private :nodoc:
|
9
9
|
if /^<.*>$/m =~ @data
|
10
10
|
@data
|
11
11
|
else
|
@@ -84,7 +84,7 @@ module RailsERD
|
|
84
84
|
module Simple
|
85
85
|
def entity_style(entity, attributes)
|
86
86
|
{}.tap do |options|
|
87
|
-
options[:fontcolor] = options[:color] = :grey60 if entity.
|
87
|
+
options[:fontcolor] = options[:color] = :grey60 if entity.virtual?
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -188,7 +188,8 @@ module RailsERD
|
|
188
188
|
save do
|
189
189
|
raise "Saving diagram failed!\nOutput directory '#{File.dirname(filename)}' does not exist." unless File.directory?(File.dirname(filename))
|
190
190
|
begin
|
191
|
-
|
191
|
+
# GraphViz doesn't like spaces in the filename
|
192
|
+
graph.output(filetype => filename.gsub(/\s/,"\\ "))
|
192
193
|
filename
|
193
194
|
rescue RuntimeError => e
|
194
195
|
raise "Saving diagram failed!\nGraphviz produced errors. Verify it has support for filetype=#{options.filetype}, or use filetype=dot." <<
|
@@ -210,10 +211,11 @@ module RailsERD
|
|
210
211
|
each_relationship do |relationship|
|
211
212
|
from, to = relationship.source, relationship.destination
|
212
213
|
unless draw_edge from.name, to.name, relationship_options(relationship)
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
214
|
+
from.children.each do |child|
|
215
|
+
draw_edge child.name, to.name, relationship_options(relationship)
|
216
|
+
end
|
217
|
+
to.children.each do |child|
|
218
|
+
draw_edge from.name, child.name, relationship_options(relationship)
|
217
219
|
end
|
218
220
|
end
|
219
221
|
end
|
data/lib/rails_erd/domain.rb
CHANGED
@@ -114,7 +114,7 @@ module RailsERD
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def models
|
117
|
-
@models ||= @source_models.
|
117
|
+
@models ||= @source_models.select { |model| check_model_validity(model) }
|
118
118
|
end
|
119
119
|
|
120
120
|
def associations
|
@@ -122,7 +122,7 @@ module RailsERD
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def check_model_validity(model)
|
125
|
-
model.table_exists? or raise "table #{model.table_name} does not exist"
|
125
|
+
model.abstract_class? or model.table_exists? or raise "table #{model.table_name} does not exist"
|
126
126
|
rescue => e
|
127
127
|
warn "Ignoring invalid model #{model.name} (#{e.message})"
|
128
128
|
end
|
@@ -62,12 +62,13 @@ module RailsERD
|
|
62
62
|
end
|
63
63
|
|
64
64
|
# Returns +true+ if this entity is a generalization, which does not
|
65
|
-
# correspond with a database table. Generalized entities are
|
65
|
+
# correspond with a database table. Generalized entities are either
|
66
|
+
# models that are defined as +abstract_class+ or they are constructed
|
66
67
|
# from polymorphic interfaces. Any +has_one+ or +has_many+ association
|
67
68
|
# that defines a polymorphic interface with <tt>:as => :name</tt> will
|
68
69
|
# lead to a generalized entity to be created.
|
69
70
|
def generalized?
|
70
|
-
!model
|
71
|
+
!model or !!model.abstract_class?
|
71
72
|
end
|
72
73
|
|
73
74
|
# Returns +true+ if this entity descends from another entity, and is
|
@@ -75,15 +76,16 @@ module RailsERD
|
|
75
76
|
# referred to as single-table inheritance. In entity-relationship
|
76
77
|
# diagrams it is called specialization.
|
77
78
|
def specialized?
|
78
|
-
|
79
|
+
!!model and !model.descends_from_active_record?
|
79
80
|
end
|
80
81
|
|
81
82
|
# Returns +true+ if this entity does not correspond directly with a
|
82
83
|
# database table (if and only if the entity is specialized or
|
83
84
|
# generalized).
|
84
|
-
def
|
85
|
-
|
85
|
+
def virtual?
|
86
|
+
generalized? or specialized?
|
86
87
|
end
|
88
|
+
alias_method :abstract?, :virtual?
|
87
89
|
|
88
90
|
# Returns all child entities, if this is a generalized entity.
|
89
91
|
def children
|
@@ -31,7 +31,7 @@ module RailsERD
|
|
31
31
|
# numbers (for source and destination). Can be any of
|
32
32
|
# +:one_to_one:+, +:one_to_many+, or +:many_to_many+. The name
|
33
33
|
# +:many_to_one+ also exists, but Rails ERD always normalises these
|
34
|
-
# kinds of relationships by
|
34
|
+
# kinds of relationships by inverting them, so they become
|
35
35
|
# +:one_to_many+ associations.
|
36
36
|
#
|
37
37
|
# You can also call the equivalent method with a question mark, which
|
@@ -1,12 +1,16 @@
|
|
1
1
|
module RailsERD
|
2
2
|
class Domain
|
3
3
|
# Describes the specialization of an entity. Specialized entites correspond
|
4
|
-
# to inheritance. In Rails, specialization is referred to
|
5
|
-
# inheritance
|
4
|
+
# to inheritance or polymorphism. In Rails, specialization is referred to
|
5
|
+
# as single table inheritance, while generalization is referred to as
|
6
|
+
# polymorphism or abstract classes.
|
6
7
|
class Specialization
|
7
8
|
class << self
|
8
9
|
def from_models(domain, models) # @private :nodoc:
|
9
|
-
|
10
|
+
models = polymorphic_from_models(domain, models) +
|
11
|
+
inheritance_from_models(domain, models) +
|
12
|
+
abstract_from_models(domain, models)
|
13
|
+
models.sort
|
10
14
|
end
|
11
15
|
|
12
16
|
private
|
@@ -24,6 +28,12 @@ module RailsERD
|
|
24
28
|
new(domain, domain.entity_by_name(model.base_class.name), domain.entity_by_name(model.name))
|
25
29
|
}
|
26
30
|
end
|
31
|
+
|
32
|
+
def abstract_from_models(domain, models)
|
33
|
+
models.select(&:abstract_class?).collect(&:descendants).flatten.collect { |model|
|
34
|
+
new(domain, domain.entity_by_name(model.superclass.name), domain.entity_by_name(model.name))
|
35
|
+
}
|
36
|
+
end
|
27
37
|
end
|
28
38
|
|
29
39
|
extend Inspectable
|
@@ -42,13 +52,15 @@ module RailsERD
|
|
42
52
|
@domain, @generalized, @specialized = domain, generalized, specialized
|
43
53
|
end
|
44
54
|
|
45
|
-
def
|
46
|
-
|
55
|
+
def generalization?
|
56
|
+
generalized.generalized?
|
47
57
|
end
|
58
|
+
alias_method :polymorphic?, :generalization?
|
48
59
|
|
49
|
-
def
|
50
|
-
|
60
|
+
def specialization?
|
61
|
+
!generalization?
|
51
62
|
end
|
63
|
+
alias_method :inheritance?, :specialization?
|
52
64
|
|
53
65
|
def <=>(other) # @private :nodoc:
|
54
66
|
(generalized.name <=> other.generalized.name).nonzero? or (specialized.name <=> other.specialized.name)
|
data/lib/rails_erd/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -39,10 +39,11 @@ class ActiveSupport::TestCase
|
|
39
39
|
superklass = args.first.kind_of?(Class) ? args.shift : ActiveRecord::Base
|
40
40
|
columns = args.first || {}
|
41
41
|
klass = Object.const_set name.to_sym, Class.new(superklass)
|
42
|
-
|
43
|
-
if superklass == ActiveRecord::Base
|
42
|
+
if superklass == ActiveRecord::Base || superklass.abstract_class?
|
44
43
|
create_table Object.const_get(name.to_sym).table_name, columns, Object.const_get(name.to_sym).primary_key rescue nil
|
45
44
|
end
|
45
|
+
klass.class_eval(&block) if block_given?
|
46
|
+
Object.const_get(name.to_sym)
|
46
47
|
end
|
47
48
|
|
48
49
|
def create_models(*names)
|
@@ -98,16 +99,23 @@ class ActiveSupport::TestCase
|
|
98
99
|
|
99
100
|
def create_specialization
|
100
101
|
create_model "Beverage", :type => :string
|
101
|
-
|
102
|
+
create_model "Beer", Beverage
|
102
103
|
end
|
103
104
|
|
104
|
-
def
|
105
|
+
def create_polymorphic_generalization
|
105
106
|
create_model "Cannon"
|
106
107
|
create_model "Galleon" do
|
107
108
|
has_many :cannons, :as => :defensible
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
112
|
+
def create_abstract_generalization
|
113
|
+
create_model "Structure" do
|
114
|
+
self.abstract_class = true
|
115
|
+
end
|
116
|
+
create_model "Palace", Structure
|
117
|
+
end
|
118
|
+
|
111
119
|
private
|
112
120
|
|
113
121
|
def reset_domain
|
data/test/unit/diagram_test.rb
CHANGED
@@ -266,26 +266,30 @@ class DiagramTest < ActiveSupport::TestCase
|
|
266
266
|
# Specialization filtering =================================================
|
267
267
|
test "generate should not yield specializations" do
|
268
268
|
create_specialization
|
269
|
-
|
269
|
+
create_polymorphic_generalization
|
270
|
+
create_abstract_generalization
|
270
271
|
assert_equal [], retrieve_specializations
|
271
272
|
end
|
272
273
|
|
273
274
|
test "generate should yield specializations but not generalizations if inheritance is true" do
|
274
275
|
create_specialization
|
275
|
-
|
276
|
+
create_polymorphic_generalization
|
277
|
+
create_abstract_generalization
|
276
278
|
assert_equal ["Beer"], retrieve_specializations(:inheritance => true).map { |s| s.specialized.name }
|
277
279
|
end
|
278
280
|
|
279
281
|
test "generate should yield generalizations but not specializations if polymorphism is true" do
|
280
282
|
create_specialization
|
281
|
-
|
282
|
-
|
283
|
+
create_polymorphic_generalization
|
284
|
+
create_abstract_generalization
|
285
|
+
assert_equal ["Galleon", "Palace"], retrieve_specializations(:polymorphism => true).map { |s| s.specialized.name }
|
283
286
|
end
|
284
287
|
|
285
288
|
test "generate should yield specializations and generalizations if polymorphism and inheritance is true" do
|
286
289
|
create_specialization
|
287
|
-
|
288
|
-
|
290
|
+
create_polymorphic_generalization
|
291
|
+
create_abstract_generalization
|
292
|
+
assert_equal ["Beer", "Galleon", "Palace"], retrieve_specializations(:inheritance => true,
|
289
293
|
:polymorphism => true).map { |s| s.specialized.name }
|
290
294
|
end
|
291
295
|
|
data/test/unit/domain_test.rb
CHANGED
@@ -64,14 +64,12 @@ class DomainTest < ActiveSupport::TestCase
|
|
64
64
|
assert_equal ["Defensible", "Galleon", "Stronghold"], Domain.generate.entities.collect(&:name)
|
65
65
|
end
|
66
66
|
|
67
|
-
test "entities should
|
68
|
-
|
69
|
-
|
70
|
-
self.table_name = "bars"
|
67
|
+
test "entities should include abstract models" do
|
68
|
+
create_model "Structure" do
|
69
|
+
self.abstract_class = true
|
71
70
|
end
|
72
|
-
|
73
|
-
|
74
|
-
assert_equal ["Bar"], Domain.generate.entities.collect(&:name)
|
71
|
+
create_model "Palace", Structure
|
72
|
+
assert_equal ["Palace", "Structure"], Domain.generate.entities.collect(&:name)
|
75
73
|
end
|
76
74
|
|
77
75
|
# Relationship processing ==================================================
|
@@ -160,37 +158,22 @@ class DomainTest < ActiveSupport::TestCase
|
|
160
158
|
assert_equal [Domain::Specialization] * 2, Domain.generate.specializations.collect(&:class)
|
161
159
|
end
|
162
160
|
|
163
|
-
test "specializations should return generalizations in domain model" do
|
164
|
-
|
165
|
-
has_many :assets, :as => :attachable
|
166
|
-
end
|
167
|
-
create_model "Asset", :attachable => :references do
|
168
|
-
belongs_to :attachable, :polymorphic => true
|
169
|
-
end
|
161
|
+
test "specializations should return polymorphic generalizations in domain model" do
|
162
|
+
create_polymorphic_generalization
|
170
163
|
assert_equal [Domain::Specialization], Domain.generate.specializations.collect(&:class)
|
171
164
|
end
|
172
165
|
|
173
|
-
test "specializations should return generalizations
|
174
|
-
|
175
|
-
|
176
|
-
end
|
177
|
-
Object.const_set :Post, Class.new(Content)
|
178
|
-
create_model "Asset", :attachable => :references do
|
179
|
-
belongs_to :attachable, :polymorphic => true
|
180
|
-
end
|
181
|
-
assert_equal [Domain::Specialization] * 2, Domain.generate.specializations.collect(&:class)
|
166
|
+
test "specializations should return abstract generalizations in domain model" do
|
167
|
+
create_abstract_generalization
|
168
|
+
assert_equal [Domain::Specialization], Domain.generate.specializations.collect(&:class)
|
182
169
|
end
|
183
170
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
# belongs_to :attachable, :polymorphic => true
|
191
|
-
# end
|
192
|
-
# assert_equal [], Domain.generate.relationships
|
193
|
-
# end
|
171
|
+
test "specializations should return polymorphic and abstract generalizations and specializations in domain model" do
|
172
|
+
create_specialization
|
173
|
+
create_polymorphic_generalization
|
174
|
+
create_abstract_generalization
|
175
|
+
assert_equal [Domain::Specialization] * 3, Domain.generate.specializations.collect(&:class)
|
176
|
+
end
|
194
177
|
|
195
178
|
# Erroneous associations ===================================================
|
196
179
|
test "relationships should omit bad has_many associations" do
|
@@ -236,7 +219,7 @@ class DomainTest < ActiveSupport::TestCase
|
|
236
219
|
assert_match /model Bar exists, but is not included in domain/, output
|
237
220
|
end
|
238
221
|
|
239
|
-
test "relationships should output a warning when an association to a non existent generalization is
|
222
|
+
test "relationships should output a warning when an association to a non existent generalization is encountered" do
|
240
223
|
create_model "Foo" do
|
241
224
|
has_many :bars, :as => :foo
|
242
225
|
end
|
data/test/unit/entity_test.rb
CHANGED
@@ -9,6 +9,11 @@ class EntityTest < ActiveSupport::TestCase
|
|
9
9
|
Domain::Entity.new(Domain.new, name)
|
10
10
|
end
|
11
11
|
|
12
|
+
def create_abstract_entity(name)
|
13
|
+
model = create_model(name) { self.abstract_class = true }
|
14
|
+
create_entity(model)
|
15
|
+
end
|
16
|
+
|
12
17
|
# Entity ===================================================================
|
13
18
|
test "model should return active record model" do
|
14
19
|
create_models "Foo"
|
@@ -63,36 +68,6 @@ class EntityTest < ActiveSupport::TestCase
|
|
63
68
|
assert_equal domain.relationships.select { |r| r.destination == foo }, foo.relationships
|
64
69
|
end
|
65
70
|
|
66
|
-
# test "parent should return nil for regular entities" do
|
67
|
-
# create_model "Foo"
|
68
|
-
# assert_nil create_entity(Foo).parent
|
69
|
-
# end
|
70
|
-
#
|
71
|
-
# test "parent should return nil for specialized entities with distinct tables" do
|
72
|
-
# create_model "Foo", :type => :string
|
73
|
-
# Object.const_set :SpecialFoo, Class.new(Foo)
|
74
|
-
# SpecialFoo.class_eval do
|
75
|
-
# self.table_name = "special_foo"
|
76
|
-
# end
|
77
|
-
# create_table "special_foo", {}, true
|
78
|
-
# assert_nil create_entity(SpecialFoo).parent
|
79
|
-
# end
|
80
|
-
#
|
81
|
-
# test "parent should return parent entity for specialized entities" do
|
82
|
-
# create_model "Foo", :type => :string
|
83
|
-
# Object.const_set :SpecialFoo, Class.new(Foo)
|
84
|
-
# domain = Domain.generate
|
85
|
-
# assert_equal domain.entity_by_name("Foo"), Domain::Entity.from_models(domain, [SpecialFoo]).first.parent
|
86
|
-
# end
|
87
|
-
#
|
88
|
-
# test "parent should return parent entity for specializations of specialized entities" do
|
89
|
-
# create_model "Foo", :type => :string
|
90
|
-
# Object.const_set :SpecialFoo, Class.new(Foo)
|
91
|
-
# Object.const_set :VerySpecialFoo, Class.new(SpecialFoo)
|
92
|
-
# domain = Domain.generate
|
93
|
-
# assert_equal domain.entity_by_name("SpecialFoo"), Domain::Entity.from_models(domain, [VerySpecialFoo]).first.parent
|
94
|
-
# end
|
95
|
-
|
96
71
|
# Entity properties ========================================================
|
97
72
|
test "connected should return false for unconnected entities" do
|
98
73
|
create_models "Foo", "Bar"
|
@@ -148,10 +123,10 @@ class EntityTest < ActiveSupport::TestCase
|
|
148
123
|
assert_equal true, create_entity(VerySpecialFoo).specialized?
|
149
124
|
end
|
150
125
|
|
151
|
-
test "
|
126
|
+
test "virtual should return true for specialized entity" do
|
152
127
|
create_model "Foo", :type => :string
|
153
128
|
Object.const_set :SpecialFoo, Class.new(Foo)
|
154
|
-
assert_equal true, create_entity(SpecialFoo).
|
129
|
+
assert_equal true, create_entity(SpecialFoo).virtual?
|
155
130
|
end
|
156
131
|
|
157
132
|
test "generalized should return false for regular entity" do
|
@@ -159,9 +134,9 @@ class EntityTest < ActiveSupport::TestCase
|
|
159
134
|
assert_equal false, create_entity(Concrete).generalized?
|
160
135
|
end
|
161
136
|
|
162
|
-
test "
|
137
|
+
test "virtual should return false for regular entity" do
|
163
138
|
create_model "Concrete"
|
164
|
-
assert_equal false, create_entity(Concrete).
|
139
|
+
assert_equal false, create_entity(Concrete).virtual?
|
165
140
|
end
|
166
141
|
|
167
142
|
# Attribute processing =====================================================
|
@@ -196,8 +171,8 @@ class EntityTest < ActiveSupport::TestCase
|
|
196
171
|
assert_equal false, create_generalized_entity("MyAbstractModel").specialized?
|
197
172
|
end
|
198
173
|
|
199
|
-
test "
|
200
|
-
assert_equal true, create_generalized_entity("MyAbstractModel").
|
174
|
+
test "virtual should return true for generalized entity" do
|
175
|
+
assert_equal true, create_generalized_entity("MyAbstractModel").virtual?
|
201
176
|
end
|
202
177
|
|
203
178
|
test "relationships should return relationships for generalized entity" do
|
@@ -213,17 +188,37 @@ class EntityTest < ActiveSupport::TestCase
|
|
213
188
|
assert_equal domain.relationships, defensible.relationships
|
214
189
|
end
|
215
190
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
191
|
+
# Abstract generalized entity ==============================================
|
192
|
+
test "name should return given name for abstract generalized entity" do
|
193
|
+
assert_equal "MyAbstractModel", create_abstract_entity("MyAbstractModel").name
|
194
|
+
end
|
195
|
+
|
196
|
+
test "attributes should return empty array for abstract generalized entity" do
|
197
|
+
assert_equal [], create_abstract_entity("MyAbstractModel").attributes
|
198
|
+
end
|
199
|
+
|
200
|
+
test "generalized should return true for abstract generalized entity" do
|
201
|
+
assert_equal true, create_abstract_entity("MyAbstractModel").generalized?
|
202
|
+
end
|
203
|
+
|
204
|
+
test "specialized should return false for abstract generalized entity" do
|
205
|
+
assert_equal false, create_abstract_entity("MyAbstractModel").specialized?
|
206
|
+
end
|
207
|
+
|
208
|
+
test "virtual should return true for abstract generalized entity" do
|
209
|
+
assert_equal true, create_abstract_entity("MyAbstractModel").virtual?
|
210
|
+
end
|
211
|
+
|
212
|
+
test "relationships should return relationships for abstract generalized entity" do
|
213
|
+
create_model "Kingdom"
|
214
|
+
create_model "Structure" do
|
215
|
+
self.abstract_class = true
|
216
|
+
belongs_to :kingdom
|
222
217
|
end
|
218
|
+
create_model "Palace", Structure, :kingdom => :references
|
223
219
|
|
224
220
|
domain = Domain.generate
|
225
|
-
|
226
|
-
assert_equal domain.relationships, defensible.relationships
|
221
|
+
assert_equal domain.relationships, domain.entity_by_name("Structure").relationships
|
227
222
|
end
|
228
223
|
|
229
224
|
# Children =================================================================
|
data/test/unit/graphviz_test.rb
CHANGED
@@ -8,7 +8,7 @@ class GraphvizTest < ActiveSupport::TestCase
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def teardown
|
11
|
-
FileUtils.rm Dir["erd
|
11
|
+
FileUtils.rm Dir["erd*.*"] rescue nil
|
12
12
|
RailsERD::Diagram.send :remove_const, :Graphviz rescue nil
|
13
13
|
end
|
14
14
|
|
@@ -92,6 +92,12 @@ class GraphvizTest < ActiveSupport::TestCase
|
|
92
92
|
assert File.exists?("erd.dot")
|
93
93
|
end
|
94
94
|
|
95
|
+
test "create should create output for filenames that have spaces" do
|
96
|
+
create_simple_domain
|
97
|
+
Diagram::Graphviz.create :filename => "erd with spaces"
|
98
|
+
assert File.exists?("erd with spaces.png")
|
99
|
+
end
|
100
|
+
|
95
101
|
test "create should write to file with dot extension without requiring graphviz" do
|
96
102
|
create_simple_domain
|
97
103
|
begin
|
@@ -298,7 +304,7 @@ class GraphvizTest < ActiveSupport::TestCase
|
|
298
304
|
assert_equal [["m_Bar", "m_Foo"], ["m_Foo", "m_Bar"]], find_dot_node_pairs(diagram).sort
|
299
305
|
end
|
300
306
|
|
301
|
-
test "generate should create edge to
|
307
|
+
test "generate should create edge to polymorphic entity if polymorphism is true" do
|
302
308
|
create_model "Cannon", :defensible => :references do
|
303
309
|
belongs_to :defensible, :polymorphic => true
|
304
310
|
end
|
@@ -312,7 +318,7 @@ class GraphvizTest < ActiveSupport::TestCase
|
|
312
318
|
find_dot_node_pairs(diagram(:polymorphism => true)).sort
|
313
319
|
end
|
314
320
|
|
315
|
-
test "generate should create edge to each child of
|
321
|
+
test "generate should create edge to each child of polymorphic entity if polymorphism is false" do
|
316
322
|
create_model "Cannon", :defensible => :references do
|
317
323
|
belongs_to :defensible, :polymorphic => true
|
318
324
|
end
|
@@ -325,6 +331,35 @@ class GraphvizTest < ActiveSupport::TestCase
|
|
325
331
|
assert_equal [["m_Galleon", "m_Cannon"], ["m_Stronghold", "m_Cannon"]], find_dot_node_pairs(diagram).sort
|
326
332
|
end
|
327
333
|
|
334
|
+
test "generate should create edge to abstract entity if polymorphism is true" do
|
335
|
+
create_model "Person", :settlement => :references
|
336
|
+
create_model "Country" do
|
337
|
+
has_many :settlements
|
338
|
+
end
|
339
|
+
create_model "Settlement" do
|
340
|
+
self.abstract_class = true
|
341
|
+
belongs_to :country
|
342
|
+
has_many :people
|
343
|
+
end
|
344
|
+
create_model "City", Settlement, :country => :references
|
345
|
+
assert_equal [["m_Country", "m_Settlement"], ["m_Settlement", "m_City"], ["m_Settlement", "m_Person"]],
|
346
|
+
find_dot_node_pairs(diagram(:polymorphism => true)).sort
|
347
|
+
end
|
348
|
+
|
349
|
+
test "generate should create edge to each child of abstract entity if polymorphism is false" do
|
350
|
+
create_model "Person", :settlement => :references
|
351
|
+
create_model "Country" do
|
352
|
+
has_many :settlements
|
353
|
+
end
|
354
|
+
create_model "Settlement" do
|
355
|
+
self.abstract_class = true
|
356
|
+
belongs_to :country
|
357
|
+
has_many :people
|
358
|
+
end
|
359
|
+
create_model "City", Settlement, :country => :references
|
360
|
+
assert_equal [["m_City", "m_Person"], ["m_Country", "m_City"]], find_dot_node_pairs(diagram).sort
|
361
|
+
end
|
362
|
+
|
328
363
|
# Simple notation style ====================================================
|
329
364
|
test "generate should use no style for one to one cardinalities with simple notation" do
|
330
365
|
create_one_to_one_assoc_domain
|
@@ -35,12 +35,22 @@ class SpecializationTest < ActiveSupport::TestCase
|
|
35
35
|
end
|
36
36
|
|
37
37
|
test "inheritance should be false for polymorphic specializations" do
|
38
|
-
|
38
|
+
create_polymorphic_generalization
|
39
39
|
assert_equal [false], Domain.generate.specializations.map(&:inheritance?)
|
40
40
|
end
|
41
41
|
|
42
42
|
test "polymorphic should be true for polymorphic specializations" do
|
43
|
-
|
43
|
+
create_polymorphic_generalization
|
44
|
+
assert_equal [true], Domain.generate.specializations.map(&:polymorphic?)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "inheritance should be false for abstract specializations" do
|
48
|
+
create_abstract_generalization
|
49
|
+
assert_equal [false], Domain.generate.specializations.map(&:inheritance?)
|
50
|
+
end
|
51
|
+
|
52
|
+
test "polymorphic should be true for abstract specializations" do
|
53
|
+
create_abstract_generalization
|
44
54
|
assert_equal [true], Domain.generate.specializations.map(&:polymorphic?)
|
45
55
|
end
|
46
56
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-erd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: activesupport
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '3.0'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: ruby-graphviz
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ~>
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: 1.0.4
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.4
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: choice
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
@@ -54,18 +69,12 @@ dependencies:
|
|
54
69
|
version: 0.1.6
|
55
70
|
type: :runtime
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: rake
|
60
|
-
requirement: &70146121977640 !ruby/object:Gem::Requirement
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
73
|
none: false
|
62
74
|
requirements:
|
63
75
|
- - ~>
|
64
76
|
- !ruby/object:Gem::Version
|
65
|
-
version:
|
66
|
-
type: :development
|
67
|
-
prerelease: false
|
68
|
-
version_requirements: *70146121977640
|
77
|
+
version: 0.1.6
|
69
78
|
description: Automatically generate an entity-relationship diagram (ERD) for your
|
70
79
|
Rails models.
|
71
80
|
email:
|
@@ -75,7 +84,6 @@ executables:
|
|
75
84
|
extensions: []
|
76
85
|
extra_rdoc_files: []
|
77
86
|
files:
|
78
|
-
- CHANGES.rdoc
|
79
87
|
- LICENSE
|
80
88
|
- README.md
|
81
89
|
- Rakefile
|
@@ -120,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
120
128
|
version: '0'
|
121
129
|
segments:
|
122
130
|
- 0
|
123
|
-
hash:
|
131
|
+
hash: 1960804951299581689
|
124
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
133
|
none: false
|
126
134
|
requirements:
|
@@ -129,10 +137,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
137
|
version: '0'
|
130
138
|
segments:
|
131
139
|
- 0
|
132
|
-
hash:
|
140
|
+
hash: 1960804951299581689
|
133
141
|
requirements: []
|
134
142
|
rubyforge_project: rails-erd
|
135
|
-
rubygems_version: 1.8.
|
143
|
+
rubygems_version: 1.8.23
|
136
144
|
signing_key:
|
137
145
|
specification_version: 3
|
138
146
|
summary: Entity-relationship diagram for your Rails models.
|
@@ -147,3 +155,4 @@ test_files:
|
|
147
155
|
- test/unit/rake_task_test.rb
|
148
156
|
- test/unit/relationship_test.rb
|
149
157
|
- test/unit/specialization_test.rb
|
158
|
+
has_rdoc:
|
data/CHANGES.rdoc
DELETED
@@ -1,94 +0,0 @@
|
|
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
|
-
|
19
|
-
=== 0.4.5:
|
20
|
-
|
21
|
-
* Display more helpful error message when the application models could not be
|
22
|
-
loaded successfully by the 'rake erd' task (reported by Greg Weber).
|
23
|
-
|
24
|
-
=== 0.4.4:
|
25
|
-
|
26
|
-
* Added the ability to disable HTML markup in node labels (markup=false). This
|
27
|
-
causes .dot files to be compatible with OmniGraffle, which otherwise fails
|
28
|
-
to import graphs with HTML node labels (issue reported by Lucas Florio,
|
29
|
-
implementation based on template by Troy Anderson).
|
30
|
-
* Prevent models named after Graphviz reserved words (Node, Edge) from causing
|
31
|
-
errors in .dot files (reported by gguthrie).
|
32
|
-
* Improved error messages when Graphviz is throwing errors (reported by
|
33
|
-
Michael Irwin).
|
34
|
-
|
35
|
-
=== 0.4.3:
|
36
|
-
|
37
|
-
* Display the scale of decimal attributes when set. A decimal attribute with
|
38
|
-
precision 5 and scale 2 is now indicated with (5,2).
|
39
|
-
* Fixed deprecation warnings for edge Rails (upcoming 3.1).
|
40
|
-
|
41
|
-
=== 0.4.1:
|
42
|
-
|
43
|
-
* Fix processing of associations with class_name set to absolute module paths.
|
44
|
-
* Adjust model loading process to include models in non-standard paths eagerly.
|
45
|
-
|
46
|
-
=== 0.4.0:
|
47
|
-
|
48
|
-
* Support to optionally display single table inheritance relationships
|
49
|
-
(inheritance=true).
|
50
|
-
* Support to optionally display polymorphic associations (polymorphism=true).
|
51
|
-
* Adjustments to 'advanced' style so that it matches original Bachman style,
|
52
|
-
and therefore now called 'bachman'.
|
53
|
-
* Ignore models without tables (reported by Mark Chapman).
|
54
|
-
* Mutual indirect relationships are now combined.
|
55
|
-
* Changed API for diagram generation.
|
56
|
-
* Restructured classes and renamed several API properties and methods.
|
57
|
-
* Added new edge type to describe single table inheritance and polymorphic
|
58
|
-
associations: Specialization.
|
59
|
-
* Added compatibility for Active Record 3.1 (beta), removed dependency on Arel.
|
60
|
-
* Rubinius compatibility.
|
61
|
-
|
62
|
-
=== 0.3.0:
|
63
|
-
|
64
|
-
* Added the ability to support multiple styles of cardinality notations.
|
65
|
-
Currently supported types are 'simple' and 'advanced'.
|
66
|
-
* Added option to exclude indirect relationships (indirect=false).
|
67
|
-
* Added option to change or disable the diagram title (title='Custom title').
|
68
|
-
* Altered the type descriptions of attributes.
|
69
|
-
* Renamed options for flexibility and clarity.
|
70
|
-
* Improved internal logic to determine the cardinality of relationships.
|
71
|
-
* More versatile API that allows you to inspect relationships and their
|
72
|
-
cardinalities.
|
73
|
-
* Changed line widths to 1.0 to avoid invisible node boundaries with older
|
74
|
-
versions of Graphviz (reported by Mike McQuinn).
|
75
|
-
* Bundled examples based on actual applications.
|
76
|
-
|
77
|
-
=== 0.2.0
|
78
|
-
|
79
|
-
* Added simple way to create your own type of diagrams with a tiny amount of code.
|
80
|
-
* Improved internal API and documentation.
|
81
|
-
* Subtle changes in diagram style.
|
82
|
-
* Fixed error where non-mutual relationships might be inadvertently classified
|
83
|
-
as indirect relationships.
|
84
|
-
* Fixed error where diagrams with a vertical layout might fail to be generated.
|
85
|
-
|
86
|
-
=== 0.1.1
|
87
|
-
|
88
|
-
* Fixed small errors in Ruby 1.8.7.
|
89
|
-
* Abort generation of diagrams when there are no models.
|
90
|
-
|
91
|
-
=== 0.1.0
|
92
|
-
|
93
|
-
* Released on September 20th, 2010.
|
94
|
-
* First public release.
|