rails-erd 0.3.0 → 0.4.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/.gitignore +1 -0
- data/CHANGES.rdoc +17 -1
- data/Gemfile +3 -2
- data/Gemfile.lock +8 -4
- data/README.md +60 -0
- data/Rakefile +10 -50
- data/VERSION +1 -1
- data/lib/rails_erd.rb +28 -1
- data/lib/rails_erd/diagram.rb +66 -33
- data/lib/rails_erd/diagram/graphviz.rb +123 -92
- data/lib/rails_erd/diagram/templates/node.erb +2 -2
- data/lib/rails_erd/domain.rb +51 -23
- data/lib/rails_erd/domain/attribute.rb +102 -0
- data/lib/rails_erd/domain/entity.rb +102 -0
- data/lib/rails_erd/domain/relationship.rb +189 -0
- data/lib/rails_erd/domain/relationship/cardinality.rb +118 -0
- data/lib/rails_erd/domain/specialization.rb +58 -0
- data/lib/rails_erd/railtie.rb +1 -1
- data/rails-erd.gemspec +19 -16
- data/test/test_helper.rb +21 -5
- data/test/unit/attribute_test.rb +35 -8
- data/test/unit/cardinality_test.rb +41 -35
- data/test/unit/diagram_test.rb +130 -43
- data/test/unit/domain_test.rb +131 -8
- data/test/unit/entity_test.rb +150 -46
- data/test/unit/graphviz_test.rb +52 -14
- data/test/unit/rake_task_test.rb +2 -2
- data/test/unit/relationship_test.rb +73 -24
- data/test/unit/specialization_test.rb +57 -0
- metadata +15 -13
- data/README.rdoc +0 -51
- data/lib/rails_erd/attribute.rb +0 -95
- data/lib/rails_erd/entity.rb +0 -73
- data/lib/rails_erd/relationship.rb +0 -177
- data/lib/rails_erd/relationship/cardinality.rb +0 -118
data/lib/rails_erd/railtie.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module RailsERD
|
2
2
|
# Rails ERD integrates with Rails 3. If you add it to your +Gemfile+, you
|
3
3
|
# will gain a Rake task called +erd+, which you can use to generate diagrams
|
4
|
-
# of your domain model.
|
4
|
+
# of your domain model.
|
5
5
|
class Railtie < Rails::Railtie
|
6
6
|
rake_tasks do
|
7
7
|
load "rails_erd/tasks.rake"
|
data/rails-erd.gemspec
CHANGED
@@ -5,16 +5,16 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rails-erd}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Rolf Timmermans"]
|
12
|
-
s.date = %q{2010-10-
|
12
|
+
s.date = %q{2010-10-12}
|
13
13
|
s.description = %q{Automatically generate an entity-relationship diagram (ERD) for your Rails models.}
|
14
14
|
s.email = %q{r.timmermans@voormedia.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
"README.
|
17
|
+
"README.md"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".gitignore",
|
@@ -22,20 +22,21 @@ Gem::Specification.new do |s|
|
|
22
22
|
"Gemfile",
|
23
23
|
"Gemfile.lock",
|
24
24
|
"LICENSE",
|
25
|
-
"README.
|
25
|
+
"README.md",
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
28
|
"lib/rails-erd.rb",
|
29
29
|
"lib/rails_erd.rb",
|
30
|
-
"lib/rails_erd/attribute.rb",
|
31
30
|
"lib/rails_erd/diagram.rb",
|
32
31
|
"lib/rails_erd/diagram/graphviz.rb",
|
33
32
|
"lib/rails_erd/diagram/templates/node.erb",
|
34
33
|
"lib/rails_erd/domain.rb",
|
35
|
-
"lib/rails_erd/
|
34
|
+
"lib/rails_erd/domain/attribute.rb",
|
35
|
+
"lib/rails_erd/domain/entity.rb",
|
36
|
+
"lib/rails_erd/domain/relationship.rb",
|
37
|
+
"lib/rails_erd/domain/relationship/cardinality.rb",
|
38
|
+
"lib/rails_erd/domain/specialization.rb",
|
36
39
|
"lib/rails_erd/railtie.rb",
|
37
|
-
"lib/rails_erd/relationship.rb",
|
38
|
-
"lib/rails_erd/relationship/cardinality.rb",
|
39
40
|
"lib/rails_erd/tasks.rake",
|
40
41
|
"rails-erd.gemspec",
|
41
42
|
"test/test_helper.rb",
|
@@ -46,7 +47,8 @@ Gem::Specification.new do |s|
|
|
46
47
|
"test/unit/entity_test.rb",
|
47
48
|
"test/unit/graphviz_test.rb",
|
48
49
|
"test/unit/rake_task_test.rb",
|
49
|
-
"test/unit/relationship_test.rb"
|
50
|
+
"test/unit/relationship_test.rb",
|
51
|
+
"test/unit/specialization_test.rb"
|
50
52
|
]
|
51
53
|
s.homepage = %q{http://rails-erd.rubyforge.org/}
|
52
54
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -63,7 +65,8 @@ Gem::Specification.new do |s|
|
|
63
65
|
"test/unit/entity_test.rb",
|
64
66
|
"test/unit/graphviz_test.rb",
|
65
67
|
"test/unit/rake_task_test.rb",
|
66
|
-
"test/unit/relationship_test.rb"
|
68
|
+
"test/unit/relationship_test.rb",
|
69
|
+
"test/unit/specialization_test.rb"
|
67
70
|
]
|
68
71
|
|
69
72
|
if s.respond_to? :specification_version then
|
@@ -71,20 +74,20 @@ Gem::Specification.new do |s|
|
|
71
74
|
s.specification_version = 3
|
72
75
|
|
73
76
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
74
|
-
s.add_runtime_dependency(%q<activerecord>, ["~> 3.0
|
77
|
+
s.add_runtime_dependency(%q<activerecord>, ["~> 3.0"])
|
75
78
|
s.add_runtime_dependency(%q<activesupport>, ["~> 3.0"])
|
76
|
-
s.add_runtime_dependency(%q<ruby-graphviz>, ["~> 0.9.
|
79
|
+
s.add_runtime_dependency(%q<ruby-graphviz>, ["~> 0.9.18"])
|
77
80
|
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
78
81
|
else
|
79
|
-
s.add_dependency(%q<activerecord>, ["~> 3.0
|
82
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0"])
|
80
83
|
s.add_dependency(%q<activesupport>, ["~> 3.0"])
|
81
|
-
s.add_dependency(%q<ruby-graphviz>, ["~> 0.9.
|
84
|
+
s.add_dependency(%q<ruby-graphviz>, ["~> 0.9.18"])
|
82
85
|
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
83
86
|
end
|
84
87
|
else
|
85
|
-
s.add_dependency(%q<activerecord>, ["~> 3.0
|
88
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0"])
|
86
89
|
s.add_dependency(%q<activesupport>, ["~> 3.0"])
|
87
|
-
s.add_dependency(%q<ruby-graphviz>, ["~> 0.9.
|
90
|
+
s.add_dependency(%q<ruby-graphviz>, ["~> 0.9.18"])
|
88
91
|
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
89
92
|
end
|
90
93
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "rubygems"
|
2
|
-
require "bundler"
|
3
|
-
Bundler.require
|
2
|
+
require "bundler/setup"
|
4
3
|
|
4
|
+
require "active_record"
|
5
5
|
require "test/unit"
|
6
6
|
require "rails_erd/domain"
|
7
7
|
|
@@ -33,10 +33,14 @@ class ActiveSupport::TestCase
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def create_model(name,
|
37
|
-
|
36
|
+
def create_model(name, *args, &block)
|
37
|
+
superklass = args.first.kind_of?(Class) ? args.shift : ActiveRecord::Base
|
38
|
+
columns = args.first || {}
|
39
|
+
klass = Object.const_set name.to_sym, Class.new(superklass)
|
38
40
|
klass.class_eval(&block) if block_given?
|
39
|
-
|
41
|
+
if superklass == ActiveRecord::Base
|
42
|
+
create_table Object.const_get(name.to_sym).table_name, columns, Object.const_get(name.to_sym).primary_key rescue nil
|
43
|
+
end
|
40
44
|
end
|
41
45
|
|
42
46
|
def create_models(*names)
|
@@ -90,6 +94,18 @@ class ActiveSupport::TestCase
|
|
90
94
|
create_table "manies_mores", :many_id => :integer, :more_id => :integer
|
91
95
|
end
|
92
96
|
|
97
|
+
def create_specialization
|
98
|
+
create_model "Beverage", :type => :string
|
99
|
+
Object.const_set :Beer, Class.new(Beverage)
|
100
|
+
end
|
101
|
+
|
102
|
+
def create_generalization
|
103
|
+
create_model "Cannon"
|
104
|
+
create_model "Galleon" do
|
105
|
+
has_many :cannons, :as => :defensible
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
93
109
|
private
|
94
110
|
|
95
111
|
def reset_domain
|
data/test/unit/attribute_test.rb
CHANGED
@@ -20,28 +20,28 @@ class AttributeTest < ActiveSupport::TestCase
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def create_attribute(model, name)
|
23
|
-
Attribute.new(Domain.generate, model, model.
|
23
|
+
Domain::Attribute.new(Domain.generate, model, model.columns_hash[name])
|
24
24
|
end
|
25
25
|
|
26
26
|
# Attribute ================================================================
|
27
27
|
test "column should return database column" do
|
28
28
|
create_model "Foo", :my_column => :string
|
29
|
-
assert_equal Foo.
|
30
|
-
Attribute.from_model(Domain.new, Foo).reject(&:primary_key?).first.column
|
29
|
+
assert_equal Foo.columns_hash["my_column"],
|
30
|
+
Domain::Attribute.from_model(Domain.new, Foo).reject(&:primary_key?).first.column
|
31
31
|
end
|
32
32
|
|
33
33
|
test "spaceship should sort attributes by name" do
|
34
34
|
create_model "Foo", :a => :string, :b => :string, :c => :string
|
35
|
-
a =
|
36
|
-
b =
|
37
|
-
c =
|
35
|
+
a = create_attribute(Foo, "a")
|
36
|
+
b = create_attribute(Foo, "b")
|
37
|
+
c = create_attribute(Foo, "c")
|
38
38
|
assert_equal [a, b, c], [c, a, b].sort
|
39
39
|
end
|
40
40
|
|
41
41
|
test "inspect should show column" do
|
42
42
|
create_model "Foo", :my_column => :string
|
43
|
-
assert_match %r{#<RailsERD::Attribute:.* @
|
44
|
-
Attribute.new(Domain.new, Foo, Foo.
|
43
|
+
assert_match %r{#<RailsERD::Domain::Attribute:.* @name="my_column" @type=:string>},
|
44
|
+
Domain::Attribute.new(Domain.new, Foo, Foo.columns_hash["my_column"]).inspect
|
45
45
|
end
|
46
46
|
|
47
47
|
test "type should return attribute type" do
|
@@ -112,6 +112,33 @@ class AttributeTest < ActiveSupport::TestCase
|
|
112
112
|
create_attribute(Foo, "created_on"), create_attribute(Foo, "updated_on")].collect(&:timestamp?)
|
113
113
|
end
|
114
114
|
|
115
|
+
test "inheritance should return false by default" do
|
116
|
+
create_model "Foo", :type => :string, :alternative => :string do
|
117
|
+
set_inheritance_column :alternative
|
118
|
+
end
|
119
|
+
assert_equal false, create_attribute(Foo, "type").inheritance?
|
120
|
+
end
|
121
|
+
|
122
|
+
test "inheritance should return if this column is used for single table inheritance" do
|
123
|
+
create_model "Foo", :type => :string, :alternative => :string do
|
124
|
+
set_inheritance_column :alternative
|
125
|
+
end
|
126
|
+
assert_equal true, create_attribute(Foo, "alternative").inheritance?
|
127
|
+
end
|
128
|
+
|
129
|
+
test "content should return true by default" do
|
130
|
+
create_model "Foo", :my_first_column => :string
|
131
|
+
assert_equal true, create_attribute(Foo, "my_first_column").content?
|
132
|
+
end
|
133
|
+
|
134
|
+
test "content should return false for primary keys, foreign keys, timestamps and inheritance columns" do
|
135
|
+
create_model "Book", :type => :string, :created_at => :datetime, :case => :references do
|
136
|
+
belongs_to :case
|
137
|
+
end
|
138
|
+
create_model "Case"
|
139
|
+
assert_equal [false] * 4, %w{id type created_at case_id}.map { |a| create_attribute(Book, a).content? }
|
140
|
+
end
|
141
|
+
|
115
142
|
# Type descriptions ========================================================
|
116
143
|
test "type_description should return short type description" do
|
117
144
|
create_model "Foo", :a => :binary
|
@@ -2,115 +2,121 @@ require File.expand_path("../test_helper", File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
class CardinalityTest < ActiveSupport::TestCase
|
4
4
|
def setup
|
5
|
-
@n = Relationship::Cardinality::N
|
5
|
+
@n = Domain::Relationship::Cardinality::N
|
6
6
|
end
|
7
7
|
|
8
|
+
# Cardinality ==============================================================
|
9
|
+
test "inspect should show source and destination ranges" do
|
10
|
+
assert_match %r{#<RailsERD::Domain::Relationship::Cardinality:.* @source_range=1\.\.1 @destination_range=1\.\.Infinity>},
|
11
|
+
Domain::Relationship::Cardinality.new(1, 1..@n).inspect
|
12
|
+
end
|
13
|
+
|
8
14
|
# Cardinality construction =================================================
|
9
15
|
test "new should return cardinality object" do
|
10
|
-
assert_kind_of Relationship::Cardinality, Relationship::Cardinality.new(1, 1..@n)
|
16
|
+
assert_kind_of Domain::Relationship::Cardinality, Domain::Relationship::Cardinality.new(1, 1..@n)
|
11
17
|
end
|
12
18
|
|
13
19
|
# Cardinality properties ===================================================
|
14
20
|
test "source_optional should return true if source range starts at zero" do
|
15
|
-
assert_equal true, Relationship::Cardinality.new(0..1, 1).source_optional?
|
21
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 1).source_optional?
|
16
22
|
end
|
17
23
|
|
18
24
|
test "source_optional should return false if source range starts at one or more" do
|
19
|
-
assert_equal false, Relationship::Cardinality.new(1..2, 0..1).source_optional?
|
25
|
+
assert_equal false, Domain::Relationship::Cardinality.new(1..2, 0..1).source_optional?
|
20
26
|
end
|
21
27
|
|
22
28
|
test "destination_optional should return true if destination range starts at zero" do
|
23
|
-
assert_equal true, Relationship::Cardinality.new(1, 0..1).destination_optional?
|
29
|
+
assert_equal true, Domain::Relationship::Cardinality.new(1, 0..1).destination_optional?
|
24
30
|
end
|
25
31
|
|
26
32
|
test "destination_optional should return false if destination range starts at one or more" do
|
27
|
-
assert_equal false, Relationship::Cardinality.new(0..1, 1..2).destination_optional?
|
33
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 1..2).destination_optional?
|
28
34
|
end
|
29
35
|
|
30
36
|
test "inverse should return inverse cardinality" do
|
31
|
-
assert_equal Relationship::Cardinality.new(23..45, 0..15), Relationship::Cardinality.new(0..15, 23..45).inverse
|
37
|
+
assert_equal Domain::Relationship::Cardinality.new(23..45, 0..15), Domain::Relationship::Cardinality.new(0..15, 23..45).inverse
|
32
38
|
end
|
33
39
|
|
34
40
|
# Cardinality equality =====================================================
|
35
41
|
test "cardinalities are equal if they have the same boundaries" do
|
36
|
-
assert_equal Relationship::Cardinality.new(1, 1..Relationship::Cardinality::N),
|
37
|
-
Relationship::Cardinality.new(1, 1..Relationship::Cardinality::N)
|
42
|
+
assert_equal Domain::Relationship::Cardinality.new(1, 1..Domain::Relationship::Cardinality::N),
|
43
|
+
Domain::Relationship::Cardinality.new(1, 1..Domain::Relationship::Cardinality::N)
|
38
44
|
end
|
39
45
|
|
40
46
|
test "cardinalities are not equal if they have a different source range" do
|
41
|
-
assert_not_equal Relationship::Cardinality.new(0..1, 1..Relationship::Cardinality::N),
|
42
|
-
Relationship::Cardinality.new(1..1, 1..Relationship::Cardinality::N)
|
47
|
+
assert_not_equal Domain::Relationship::Cardinality.new(0..1, 1..Domain::Relationship::Cardinality::N),
|
48
|
+
Domain::Relationship::Cardinality.new(1..1, 1..Domain::Relationship::Cardinality::N)
|
43
49
|
end
|
44
50
|
|
45
51
|
test "cardinalities are not equal if they have a different destination range" do
|
46
|
-
assert_not_equal Relationship::Cardinality.new(0..1, 1..Relationship::Cardinality::N),
|
47
|
-
Relationship::Cardinality.new(0..1, 2..Relationship::Cardinality::N)
|
52
|
+
assert_not_equal Domain::Relationship::Cardinality.new(0..1, 1..Domain::Relationship::Cardinality::N),
|
53
|
+
Domain::Relationship::Cardinality.new(0..1, 2..Domain::Relationship::Cardinality::N)
|
48
54
|
end
|
49
55
|
|
50
56
|
# Cardinal names ===========================================================
|
51
57
|
test "one_to_one should return true if source and destination are exactly one" do
|
52
|
-
assert_equal true, Relationship::Cardinality.new(1, 1).one_to_one?
|
58
|
+
assert_equal true, Domain::Relationship::Cardinality.new(1, 1).one_to_one?
|
53
59
|
end
|
54
60
|
|
55
61
|
test "one_to_one should return true if source and destination range are less than or equal to one" do
|
56
|
-
assert_equal true, Relationship::Cardinality.new(0..1, 0..1).one_to_one?
|
62
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 0..1).one_to_one?
|
57
63
|
end
|
58
64
|
|
59
65
|
test "one_to_one should return false if source range upper limit is more than one" do
|
60
|
-
assert_equal false, Relationship::Cardinality.new(0..15, 0..1).one_to_one?
|
66
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..15, 0..1).one_to_one?
|
61
67
|
end
|
62
68
|
|
63
69
|
test "one_to_one should return false if destination range upper limit is more than one" do
|
64
|
-
assert_equal false, Relationship::Cardinality.new(0..1, 0..15).one_to_one?
|
70
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 0..15).one_to_one?
|
65
71
|
end
|
66
72
|
|
67
73
|
test "one_to_many should return true if source is exactly one and destination is higher than one" do
|
68
|
-
assert_equal true, Relationship::Cardinality.new(1, 15).one_to_many?
|
74
|
+
assert_equal true, Domain::Relationship::Cardinality.new(1, 15).one_to_many?
|
69
75
|
end
|
70
76
|
|
71
77
|
test "one_to_many should return true if source is less than or equal to one and destination is higher than one" do
|
72
|
-
assert_equal true, Relationship::Cardinality.new(0..1, 0..15).one_to_many?
|
78
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 0..15).one_to_many?
|
73
79
|
end
|
74
80
|
|
75
81
|
test "one_to_many should return false if source range upper limit is more than one" do
|
76
|
-
assert_equal false, Relationship::Cardinality.new(0..15, 0..15).one_to_many?
|
82
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..15, 0..15).one_to_many?
|
77
83
|
end
|
78
84
|
|
79
85
|
test "one_to_many should return false if destination range upper limit is one" do
|
80
|
-
assert_equal false, Relationship::Cardinality.new(0..1, 1).one_to_many?
|
86
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 1).one_to_many?
|
81
87
|
end
|
82
88
|
|
83
89
|
test "many_to_many should return true if source and destination are higher than one" do
|
84
|
-
assert_equal true, Relationship::Cardinality.new(15, 15).many_to_many?
|
90
|
+
assert_equal true, Domain::Relationship::Cardinality.new(15, 15).many_to_many?
|
85
91
|
end
|
86
92
|
|
87
93
|
test "many_to_many should return true if source and destination upper limits are higher than one" do
|
88
|
-
assert_equal true, Relationship::Cardinality.new(0..15, 0..15).many_to_many?
|
94
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..15, 0..15).many_to_many?
|
89
95
|
end
|
90
96
|
|
91
97
|
test "many_to_many should return false if source range upper limit is is one" do
|
92
|
-
assert_equal false, Relationship::Cardinality.new(1, 0..15).many_to_many?
|
98
|
+
assert_equal false, Domain::Relationship::Cardinality.new(1, 0..15).many_to_many?
|
93
99
|
end
|
94
100
|
|
95
101
|
test "many_to_many should return false if destination range upper limit is one" do
|
96
|
-
assert_equal false, Relationship::Cardinality.new(0..1, 1).many_to_many?
|
102
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 1).many_to_many?
|
97
103
|
end
|
98
104
|
|
99
105
|
test "inverse of one_to_many should be many_to_one" do
|
100
|
-
assert_equal true, Relationship::Cardinality.new(0..1, 0..@n).inverse.many_to_one?
|
106
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 0..@n).inverse.many_to_one?
|
101
107
|
end
|
102
108
|
|
103
109
|
# Cardinality order ========================================================
|
104
110
|
test "cardinalities should be sorted in order of maniness" do
|
105
|
-
card1 = Relationship::Cardinality.new(0..1, 1)
|
106
|
-
card2 = Relationship::Cardinality.new(1, 1)
|
107
|
-
card3 = Relationship::Cardinality.new(0..1, 1..3)
|
108
|
-
card4 = Relationship::Cardinality.new(1, 1..2)
|
109
|
-
card5 = Relationship::Cardinality.new(1, 1..@n)
|
110
|
-
card6 = Relationship::Cardinality.new(1..5, 1..3)
|
111
|
-
card7 = Relationship::Cardinality.new(1..2, 1..15)
|
112
|
-
card8 = Relationship::Cardinality.new(1..15, 1..@n)
|
113
|
-
card9 = Relationship::Cardinality.new(1..@n, 1..@n)
|
111
|
+
card1 = Domain::Relationship::Cardinality.new(0..1, 1)
|
112
|
+
card2 = Domain::Relationship::Cardinality.new(1, 1)
|
113
|
+
card3 = Domain::Relationship::Cardinality.new(0..1, 1..3)
|
114
|
+
card4 = Domain::Relationship::Cardinality.new(1, 1..2)
|
115
|
+
card5 = Domain::Relationship::Cardinality.new(1, 1..@n)
|
116
|
+
card6 = Domain::Relationship::Cardinality.new(1..5, 1..3)
|
117
|
+
card7 = Domain::Relationship::Cardinality.new(1..2, 1..15)
|
118
|
+
card8 = Domain::Relationship::Cardinality.new(1..15, 1..@n)
|
119
|
+
card9 = Domain::Relationship::Cardinality.new(1..@n, 1..@n)
|
114
120
|
assert_equal [card1, card2, card3, card4, card5, card6, card7, card8, card9],
|
115
121
|
[card9, card5, card8, card2, card4, card7, card1, card6, card3].sort
|
116
122
|
end
|
data/test/unit/diagram_test.rb
CHANGED
@@ -9,35 +9,47 @@ class DiagramTest < ActiveSupport::TestCase
|
|
9
9
|
RailsERD.send :remove_const, :Diagram
|
10
10
|
end
|
11
11
|
|
12
|
+
def retrieve_entities(options = {})
|
13
|
+
klass = Class.new(Diagram)
|
14
|
+
[].tap do |entities|
|
15
|
+
klass.class_eval do
|
16
|
+
each_entity do |entity, attributes|
|
17
|
+
entities << entity
|
18
|
+
end
|
19
|
+
end
|
20
|
+
klass.create(options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
12
24
|
def retrieve_relationships(options = {})
|
13
25
|
klass = Class.new(Diagram)
|
14
26
|
[].tap do |relationships|
|
15
27
|
klass.class_eval do
|
16
|
-
|
28
|
+
each_relationship do |relationship|
|
17
29
|
relationships << relationship
|
18
30
|
end
|
19
31
|
end
|
20
32
|
klass.create(options)
|
21
33
|
end
|
22
34
|
end
|
23
|
-
|
24
|
-
def
|
35
|
+
|
36
|
+
def retrieve_specializations(options = {})
|
25
37
|
klass = Class.new(Diagram)
|
26
|
-
[].tap do |
|
38
|
+
[].tap do |specializations|
|
27
39
|
klass.class_eval do
|
28
|
-
|
29
|
-
|
40
|
+
each_specialization do |specialization|
|
41
|
+
specializations << specialization
|
30
42
|
end
|
31
43
|
end
|
32
44
|
klass.create(options)
|
33
45
|
end
|
34
46
|
end
|
35
|
-
|
47
|
+
|
36
48
|
def retrieve_attribute_lists(options = {})
|
37
49
|
klass = Class.new(Diagram)
|
38
50
|
{}.tap do |attribute_lists|
|
39
51
|
klass.class_eval do
|
40
|
-
|
52
|
+
each_entity do |entity, attributes|
|
41
53
|
attribute_lists[entity.model] = attributes
|
42
54
|
end
|
43
55
|
end
|
@@ -46,10 +58,56 @@ class DiagramTest < ActiveSupport::TestCase
|
|
46
58
|
end
|
47
59
|
|
48
60
|
# Diagram ==================================================================
|
61
|
+
test "domain sould return given domain" do
|
62
|
+
domain = Object.new
|
63
|
+
assert_same domain, Class.new(Diagram).new(domain).domain
|
64
|
+
end
|
65
|
+
|
66
|
+
# Diagram DSL ==============================================================
|
67
|
+
test "create should succeed silently if called on abstract class" do
|
68
|
+
create_simple_domain
|
69
|
+
assert_nothing_raised do
|
70
|
+
Diagram.create
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
test "create should succeed if called on subclass" do
|
75
|
+
create_simple_domain
|
76
|
+
assert_nothing_raised do
|
77
|
+
Class.new(Diagram).create
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
test "create should call callbacks in instance in specific order" do
|
82
|
+
create_simple_domain
|
83
|
+
executed_calls = Class.new(Diagram) do
|
84
|
+
setup do
|
85
|
+
calls << :setup
|
86
|
+
end
|
87
|
+
|
88
|
+
each_entity do
|
89
|
+
calls << :entity
|
90
|
+
end
|
91
|
+
|
92
|
+
each_relationship do
|
93
|
+
calls << :relationship
|
94
|
+
end
|
95
|
+
|
96
|
+
save do
|
97
|
+
calls << :save
|
98
|
+
end
|
99
|
+
|
100
|
+
def calls
|
101
|
+
@calls ||= []
|
102
|
+
end
|
103
|
+
end.create
|
104
|
+
assert_equal [:setup, :entity, :entity, :relationship, :save], executed_calls
|
105
|
+
end
|
106
|
+
|
49
107
|
test "create class method should return result of save" do
|
50
108
|
create_simple_domain
|
51
109
|
subclass = Class.new(Diagram) do
|
52
|
-
|
110
|
+
save do
|
53
111
|
"foobar"
|
54
112
|
end
|
55
113
|
end
|
@@ -59,38 +117,13 @@ class DiagramTest < ActiveSupport::TestCase
|
|
59
117
|
test "create should return result of save" do
|
60
118
|
create_simple_domain
|
61
119
|
diagram = Class.new(Diagram) do
|
62
|
-
|
120
|
+
save do
|
63
121
|
"foobar"
|
64
122
|
end
|
65
123
|
end.new(Domain.generate)
|
66
124
|
assert_equal "foobar", diagram.create
|
67
125
|
end
|
68
126
|
|
69
|
-
test "domain sould return given domain" do
|
70
|
-
domain = Object.new
|
71
|
-
assert_same domain, Class.new(Diagram).new(domain).domain
|
72
|
-
end
|
73
|
-
|
74
|
-
# Diagram abstractness =====================================================
|
75
|
-
test "create should succeed silently if called on abstract class" do
|
76
|
-
create_simple_domain
|
77
|
-
assert_nothing_raised do
|
78
|
-
Diagram.create
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
test "create should succeed if called on class that implements process_entity and process_relationship" do
|
83
|
-
create_simple_domain
|
84
|
-
assert_nothing_raised do
|
85
|
-
Class.new(Diagram) do
|
86
|
-
def process_entity(*args)
|
87
|
-
end
|
88
|
-
def process_relationship(*args)
|
89
|
-
end
|
90
|
-
end.create
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
127
|
# Entity filtering =========================================================
|
95
128
|
test "generate should yield entities" do
|
96
129
|
create_model "Foo"
|
@@ -111,13 +144,19 @@ class DiagramTest < ActiveSupport::TestCase
|
|
111
144
|
assert_equal [Foo], retrieve_entities(:disconnected => true).map(&:model)
|
112
145
|
end
|
113
146
|
|
114
|
-
test "generate should filter
|
147
|
+
test "generate should filter specialized entities" do
|
115
148
|
create_model "Foo", :type => :string
|
116
149
|
Object.const_set :SpecialFoo, Class.new(Foo)
|
117
150
|
assert_equal [Foo], retrieve_entities.map(&:model)
|
118
151
|
end
|
119
152
|
|
120
|
-
test "generate should yield
|
153
|
+
test "generate should yield specialized entities if inheritance is true" do
|
154
|
+
create_model "Foo", :type => :string
|
155
|
+
Object.const_set :SpecialFoo, Class.new(Foo)
|
156
|
+
assert_equal [Foo, SpecialFoo], retrieve_entities(:inheritance => true).map(&:model)
|
157
|
+
end
|
158
|
+
|
159
|
+
test "generate should yield specialized entities with distinct tables" do
|
121
160
|
create_model "Foo"
|
122
161
|
Object.const_set :SpecialFoo, Class.new(Foo)
|
123
162
|
SpecialFoo.class_eval do
|
@@ -126,6 +165,22 @@ class DiagramTest < ActiveSupport::TestCase
|
|
126
165
|
create_table "special_foo", {}, true
|
127
166
|
assert_equal [Foo, SpecialFoo], retrieve_entities.map(&:model)
|
128
167
|
end
|
168
|
+
|
169
|
+
test "generate should filter generalized entities" do
|
170
|
+
create_model "Cannon"
|
171
|
+
create_model "Galleon" do
|
172
|
+
has_many :cannons, :as => :defensible
|
173
|
+
end
|
174
|
+
assert_equal ["Cannon", "Galleon"], retrieve_entities.map(&:name)
|
175
|
+
end
|
176
|
+
|
177
|
+
test "generate should yield generalized entities if polymorphism is true" do
|
178
|
+
create_model "Cannon"
|
179
|
+
create_model "Galleon" do
|
180
|
+
has_many :cannons, :as => :defensible
|
181
|
+
end
|
182
|
+
assert_equal ["Cannon", "Defensible", "Galleon"], retrieve_entities(:polymorphism => true).map(&:name)
|
183
|
+
end
|
129
184
|
|
130
185
|
# Relationship filtering ===================================================
|
131
186
|
test "generate should yield relationships" do
|
@@ -163,27 +218,53 @@ class DiagramTest < ActiveSupport::TestCase
|
|
163
218
|
assert_equal [false, false], retrieve_relationships(:indirect => false).map(&:indirect?)
|
164
219
|
end
|
165
220
|
|
166
|
-
test "generate should
|
221
|
+
test "generate should yield relationships from specialized entities" do
|
167
222
|
create_model "Foo", :bar => :references
|
168
223
|
create_model "Bar", :type => :string
|
169
224
|
Object.const_set :SpecialBar, Class.new(Bar)
|
170
225
|
SpecialBar.class_eval do
|
171
226
|
has_many :foos
|
172
227
|
end
|
173
|
-
assert_equal
|
228
|
+
assert_equal 1, retrieve_relationships.length
|
174
229
|
end
|
175
230
|
|
176
|
-
test "generate should
|
231
|
+
test "generate should yield relationships to specialized entities" do
|
177
232
|
create_model "Foo", :type => :string, :bar => :references
|
178
233
|
Object.const_set :SpecialFoo, Class.new(Foo)
|
179
234
|
create_model "Bar" do
|
180
235
|
has_many :special_foos
|
181
236
|
end
|
182
|
-
assert_equal
|
237
|
+
assert_equal 1, retrieve_relationships.length
|
238
|
+
end
|
239
|
+
|
240
|
+
# Specialization filtering =================================================
|
241
|
+
test "generate should not yield specializations" do
|
242
|
+
create_specialization
|
243
|
+
create_generalization
|
244
|
+
assert_equal [], retrieve_specializations
|
245
|
+
end
|
246
|
+
|
247
|
+
test "generate should yield specializations but not generalizations if inheritance is true" do
|
248
|
+
create_specialization
|
249
|
+
create_generalization
|
250
|
+
assert_equal ["Beer"], retrieve_specializations(:inheritance => true).map { |s| s.specialized.name }
|
251
|
+
end
|
252
|
+
|
253
|
+
test "generate should yield generalizations but not specializations if polymorphism is true" do
|
254
|
+
create_specialization
|
255
|
+
create_generalization
|
256
|
+
assert_equal ["Galleon"], retrieve_specializations(:polymorphism => true).map { |s| s.specialized.name }
|
257
|
+
end
|
258
|
+
|
259
|
+
test "generate should yield specializations and generalizations if polymorphism and inheritance is true" do
|
260
|
+
create_specialization
|
261
|
+
create_generalization
|
262
|
+
assert_equal ["Beer", "Galleon"], retrieve_specializations(:inheritance => true,
|
263
|
+
:polymorphism => true).map { |s| s.specialized.name }
|
183
264
|
end
|
184
265
|
|
185
266
|
# Attribute filtering ======================================================
|
186
|
-
test "generate should yield
|
267
|
+
test "generate should yield content attributes by default" do
|
187
268
|
create_model "Book", :title => :string, :created_at => :datetime, :author => :references do
|
188
269
|
belongs_to :author
|
189
270
|
end
|
@@ -222,6 +303,12 @@ class DiagramTest < ActiveSupport::TestCase
|
|
222
303
|
end
|
223
304
|
create_model "Author"
|
224
305
|
assert_equal %w{created_at title},
|
225
|
-
retrieve_attribute_lists(:attributes => [:
|
306
|
+
retrieve_attribute_lists(:attributes => [:content, :timestamps])[Book].map(&:name)
|
307
|
+
end
|
308
|
+
|
309
|
+
test "generate should yield no attributes for specialized entities" do
|
310
|
+
create_model "Beverage", :type => :string, :name => :string, :distillery => :string, :age => :integer
|
311
|
+
Object.const_set :Whisky, Class.new(Beverage)
|
312
|
+
assert_equal [], retrieve_attribute_lists(:inheritance => true)[Whisky].map(&:name)
|
226
313
|
end
|
227
314
|
end
|