jw-rails-erd 1.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +86 -0
- data/Rakefile +20 -0
- data/bin/erd +4 -0
- data/lib/generators/erd/USAGE +4 -0
- data/lib/generators/erd/install_generator.rb +14 -0
- data/lib/generators/erd/templates/auto_generate_diagram.rake +6 -0
- data/lib/rails-erd.rb +1 -0
- data/lib/rails_erd/cli.rb +164 -0
- data/lib/rails_erd/config.rb +97 -0
- data/lib/rails_erd/custom.rb +99 -0
- data/lib/rails_erd/diagram/graphviz.rb +295 -0
- data/lib/rails_erd/diagram/templates/node.html.erb +14 -0
- data/lib/rails_erd/diagram/templates/node.record.erb +4 -0
- data/lib/rails_erd/diagram.rb +188 -0
- data/lib/rails_erd/domain/attribute.rb +160 -0
- data/lib/rails_erd/domain/entity.rb +104 -0
- data/lib/rails_erd/domain/relationship/cardinality.rb +118 -0
- data/lib/rails_erd/domain/relationship.rb +203 -0
- data/lib/rails_erd/domain/specialization.rb +90 -0
- data/lib/rails_erd/domain.rb +153 -0
- data/lib/rails_erd/railtie.rb +10 -0
- data/lib/rails_erd/tasks.rake +58 -0
- data/lib/rails_erd/version.rb +4 -0
- data/lib/rails_erd.rb +73 -0
- data/lib/tasks/auto_generate_diagram.rake +21 -0
- data/test/support_files/erdconfig.another_example +3 -0
- data/test/support_files/erdconfig.example +19 -0
- data/test/support_files/erdconfig.exclude.example +19 -0
- data/test/test_helper.rb +160 -0
- data/test/unit/attribute_test.rb +316 -0
- data/test/unit/cardinality_test.rb +123 -0
- data/test/unit/config_test.rb +110 -0
- data/test/unit/diagram_test.rb +352 -0
- data/test/unit/domain_test.rb +258 -0
- data/test/unit/entity_test.rb +252 -0
- data/test/unit/graphviz_test.rb +461 -0
- data/test/unit/rake_task_test.rb +174 -0
- data/test/unit/relationship_test.rb +476 -0
- data/test/unit/specialization_test.rb +67 -0
- metadata +155 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class CardinalityTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
@n = Domain::Relationship::Cardinality::N
|
6
|
+
end
|
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
|
+
|
14
|
+
# Cardinality construction =================================================
|
15
|
+
test "new should return cardinality object" do
|
16
|
+
assert_kind_of Domain::Relationship::Cardinality, Domain::Relationship::Cardinality.new(1, 1..@n)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Cardinality properties ===================================================
|
20
|
+
test "source_optional should return true if source range starts at zero" do
|
21
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 1).source_optional?
|
22
|
+
end
|
23
|
+
|
24
|
+
test "source_optional should return false if source range starts at one or more" do
|
25
|
+
assert_equal false, Domain::Relationship::Cardinality.new(1..2, 0..1).source_optional?
|
26
|
+
end
|
27
|
+
|
28
|
+
test "destination_optional should return true if destination range starts at zero" do
|
29
|
+
assert_equal true, Domain::Relationship::Cardinality.new(1, 0..1).destination_optional?
|
30
|
+
end
|
31
|
+
|
32
|
+
test "destination_optional should return false if destination range starts at one or more" do
|
33
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 1..2).destination_optional?
|
34
|
+
end
|
35
|
+
|
36
|
+
test "inverse should return inverse cardinality" do
|
37
|
+
assert_equal Domain::Relationship::Cardinality.new(23..45, 0..15), Domain::Relationship::Cardinality.new(0..15, 23..45).inverse
|
38
|
+
end
|
39
|
+
|
40
|
+
# Cardinality equality =====================================================
|
41
|
+
test "cardinalities are equal if they have the same boundaries" do
|
42
|
+
assert_equal Domain::Relationship::Cardinality.new(1, 1..Domain::Relationship::Cardinality::N),
|
43
|
+
Domain::Relationship::Cardinality.new(1, 1..Domain::Relationship::Cardinality::N)
|
44
|
+
end
|
45
|
+
|
46
|
+
test "cardinalities are not equal if they have a different source range" do
|
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)
|
49
|
+
end
|
50
|
+
|
51
|
+
test "cardinalities are not equal if they have a different destination range" do
|
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)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Cardinal names ===========================================================
|
57
|
+
test "one_to_one should return true if source and destination are exactly one" do
|
58
|
+
assert_equal true, Domain::Relationship::Cardinality.new(1, 1).one_to_one?
|
59
|
+
end
|
60
|
+
|
61
|
+
test "one_to_one should return true if source and destination range are less than or equal to one" do
|
62
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 0..1).one_to_one?
|
63
|
+
end
|
64
|
+
|
65
|
+
test "one_to_one should return false if source range upper limit is more than one" do
|
66
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..15, 0..1).one_to_one?
|
67
|
+
end
|
68
|
+
|
69
|
+
test "one_to_one should return false if destination range upper limit is more than one" do
|
70
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 0..15).one_to_one?
|
71
|
+
end
|
72
|
+
|
73
|
+
test "one_to_many should return true if source is exactly one and destination is higher than one" do
|
74
|
+
assert_equal true, Domain::Relationship::Cardinality.new(1, 15).one_to_many?
|
75
|
+
end
|
76
|
+
|
77
|
+
test "one_to_many should return true if source is less than or equal to one and destination is higher than one" do
|
78
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 0..15).one_to_many?
|
79
|
+
end
|
80
|
+
|
81
|
+
test "one_to_many should return false if source range upper limit is more than one" do
|
82
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..15, 0..15).one_to_many?
|
83
|
+
end
|
84
|
+
|
85
|
+
test "one_to_many should return false if destination range upper limit is one" do
|
86
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 1).one_to_many?
|
87
|
+
end
|
88
|
+
|
89
|
+
test "many_to_many should return true if source and destination are higher than one" do
|
90
|
+
assert_equal true, Domain::Relationship::Cardinality.new(15, 15).many_to_many?
|
91
|
+
end
|
92
|
+
|
93
|
+
test "many_to_many should return true if source and destination upper limits are higher than one" do
|
94
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..15, 0..15).many_to_many?
|
95
|
+
end
|
96
|
+
|
97
|
+
test "many_to_many should return false if source range upper limit is is one" do
|
98
|
+
assert_equal false, Domain::Relationship::Cardinality.new(1, 0..15).many_to_many?
|
99
|
+
end
|
100
|
+
|
101
|
+
test "many_to_many should return false if destination range upper limit is one" do
|
102
|
+
assert_equal false, Domain::Relationship::Cardinality.new(0..1, 1).many_to_many?
|
103
|
+
end
|
104
|
+
|
105
|
+
test "inverse of one_to_many should be many_to_one" do
|
106
|
+
assert_equal true, Domain::Relationship::Cardinality.new(0..1, 0..@n).inverse.many_to_one?
|
107
|
+
end
|
108
|
+
|
109
|
+
# Cardinality order ========================================================
|
110
|
+
test "cardinalities should be sorted in order of maniness" do
|
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)
|
120
|
+
assert_equal [card1, card2, card3, card4, card5, card6, card7, card8, card9],
|
121
|
+
[card9, card5, card8, card2, card4, card7, card1, card6, card3].sort
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
3
|
+
|
4
|
+
class ConfigTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
test "load_config_gile should return blank hash when neither CURRENT_CONFIG_FILE nor USER_WIDE_CONFIG_FILE exist." do
|
7
|
+
expected_hash = {}
|
8
|
+
assert_equal expected_hash, RailsERD::Config.load
|
9
|
+
end
|
10
|
+
|
11
|
+
test "load_config_gile should return a hash from USER_WIDE_CONFIG_FILE when only USER_WIDE_CONFIG_FILE exists." do
|
12
|
+
set_user_config_file_to("erdconfig.example")
|
13
|
+
|
14
|
+
expected_hash = {
|
15
|
+
attributes: [:content, :foreign_key, :inheritance, :false],
|
16
|
+
disconnected: true,
|
17
|
+
filename: "erd",
|
18
|
+
filetype: :pdf,
|
19
|
+
indirect: true,
|
20
|
+
inheritance: false,
|
21
|
+
markup: true,
|
22
|
+
notation: :simple,
|
23
|
+
orientation: :horizontal,
|
24
|
+
polymorphism: false,
|
25
|
+
warn: true,
|
26
|
+
title: "sample title",
|
27
|
+
exclude: [],
|
28
|
+
only: []
|
29
|
+
}
|
30
|
+
assert_equal expected_hash, RailsERD::Config.load
|
31
|
+
end
|
32
|
+
|
33
|
+
test "load_config_file should return a hash from USER_WIDE_CONFIG_FILE when only USER_WIDE_CONFIG_FILE exists." do
|
34
|
+
set_user_config_file_to("erdconfig.exclude.example")
|
35
|
+
|
36
|
+
expected_hash = {
|
37
|
+
attributes: [:content, :foreign_key, :inheritance, :false],
|
38
|
+
disconnected: true,
|
39
|
+
filename: "erd",
|
40
|
+
filetype: :pdf,
|
41
|
+
indirect: true,
|
42
|
+
inheritance: false,
|
43
|
+
markup: true,
|
44
|
+
notation: :simple,
|
45
|
+
orientation: :horizontal,
|
46
|
+
polymorphism: false,
|
47
|
+
warn: true,
|
48
|
+
title: "sample title",
|
49
|
+
exclude: ['Book', 'Author'],
|
50
|
+
only: []
|
51
|
+
}
|
52
|
+
assert_equal expected_hash, RailsERD::Config.load
|
53
|
+
end
|
54
|
+
|
55
|
+
test "load_config_gile should return a hash from CURRENT_CONFIG_FILE when only CURRENT_CONFIG_FILE exists." do
|
56
|
+
set_local_config_file_to("erdconfig.another_example")
|
57
|
+
|
58
|
+
expected_hash = {
|
59
|
+
:attributes => [:primary_key]
|
60
|
+
}
|
61
|
+
assert_equal expected_hash, RailsERD::Config.load
|
62
|
+
end
|
63
|
+
|
64
|
+
test "load_config_gile should return a hash from CURRENT_CONFIG_FILE overriding USER_WIDE_CONFIG_FILE when both of them exist." do
|
65
|
+
set_user_config_file_to("erdconfig.example")
|
66
|
+
set_local_config_file_to("erdconfig.another_example")
|
67
|
+
|
68
|
+
expected_hash = {
|
69
|
+
attributes: [:primary_key],
|
70
|
+
disconnected: true,
|
71
|
+
filename: "erd",
|
72
|
+
filetype: :pdf,
|
73
|
+
indirect: true,
|
74
|
+
inheritance: false,
|
75
|
+
markup: true,
|
76
|
+
notation: :simple,
|
77
|
+
orientation: :horizontal,
|
78
|
+
polymorphism: false,
|
79
|
+
warn: true,
|
80
|
+
title: "sample title",
|
81
|
+
exclude: [],
|
82
|
+
only: []
|
83
|
+
}
|
84
|
+
assert_equal expected_hash, RailsERD::Config.load
|
85
|
+
end
|
86
|
+
|
87
|
+
test "normalize_value should return symbols in an array when key is :attributes and value is a comma-joined string." do
|
88
|
+
assert_equal [:content, :foreign_keys], normalize_value(:attributes, "content,foreign_keys")
|
89
|
+
end
|
90
|
+
|
91
|
+
test "normalize_value should return symbols in an array when key is :attributes and value is strings in an array." do
|
92
|
+
assert_equal [:content, :primary_keys], normalize_value(:attributes, ["content", "primary_keys"])
|
93
|
+
end
|
94
|
+
|
95
|
+
def normalize_value(key, value)
|
96
|
+
RailsERD::Config.new.send(:normalize_value, key, value)
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_user_config_file_to(config_file)
|
100
|
+
RailsERD::Config.send :remove_const, :USER_WIDE_CONFIG_FILE
|
101
|
+
RailsERD::Config.send :const_set, :USER_WIDE_CONFIG_FILE,
|
102
|
+
File.expand_path("test/support_files/#{config_file}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_local_config_file_to(config_file)
|
106
|
+
RailsERD::Config.send :remove_const, :CURRENT_CONFIG_FILE
|
107
|
+
RailsERD::Config.send :const_set, :CURRENT_CONFIG_FILE,
|
108
|
+
File.expand_path("test/support_files/#{config_file}")
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,352 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
require "rails_erd/diagram"
|
3
|
+
|
4
|
+
class DiagramTest < ActiveSupport::TestCase
|
5
|
+
def retrieve_entities(options = {})
|
6
|
+
klass = Class.new(Diagram)
|
7
|
+
[].tap do |entities|
|
8
|
+
klass.class_eval do
|
9
|
+
each_entity do |entity, attributes|
|
10
|
+
entities << entity
|
11
|
+
end
|
12
|
+
end
|
13
|
+
klass.create(options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def retrieve_relationships(options = {})
|
18
|
+
klass = Class.new(Diagram)
|
19
|
+
[].tap do |relationships|
|
20
|
+
klass.class_eval do
|
21
|
+
each_relationship do |relationship|
|
22
|
+
relationships << relationship
|
23
|
+
end
|
24
|
+
end
|
25
|
+
klass.create(options)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def retrieve_specializations(options = {})
|
30
|
+
klass = Class.new(Diagram)
|
31
|
+
[].tap do |specializations|
|
32
|
+
klass.class_eval do
|
33
|
+
each_specialization do |specialization|
|
34
|
+
specializations << specialization
|
35
|
+
end
|
36
|
+
end
|
37
|
+
klass.create(options)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def retrieve_attribute_lists(options = {})
|
42
|
+
klass = Class.new(Diagram)
|
43
|
+
{}.tap do |attribute_lists|
|
44
|
+
klass.class_eval do
|
45
|
+
each_entity do |entity, attributes|
|
46
|
+
attribute_lists[entity.model] = attributes
|
47
|
+
end
|
48
|
+
end
|
49
|
+
klass.create(options)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Diagram ==================================================================
|
54
|
+
test "domain sould return given domain" do
|
55
|
+
domain = Object.new
|
56
|
+
assert_same domain, Class.new(Diagram).new(domain).domain
|
57
|
+
end
|
58
|
+
|
59
|
+
# Diagram DSL ==============================================================
|
60
|
+
test "create should succeed silently if called on abstract class" do
|
61
|
+
create_simple_domain
|
62
|
+
assert_nothing_raised do
|
63
|
+
Diagram.create
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
test "create should succeed if called on subclass" do
|
68
|
+
create_simple_domain
|
69
|
+
assert_nothing_raised do
|
70
|
+
Class.new(Diagram).create
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
test "create should call callbacks in instance in specific order" do
|
75
|
+
create_simple_domain
|
76
|
+
executed_calls = Class.new(Diagram) do
|
77
|
+
setup do
|
78
|
+
calls << :setup
|
79
|
+
end
|
80
|
+
|
81
|
+
each_entity do
|
82
|
+
calls << :entity
|
83
|
+
end
|
84
|
+
|
85
|
+
each_relationship do
|
86
|
+
calls << :relationship
|
87
|
+
end
|
88
|
+
|
89
|
+
save do
|
90
|
+
calls << :save
|
91
|
+
end
|
92
|
+
|
93
|
+
def calls
|
94
|
+
@calls ||= []
|
95
|
+
end
|
96
|
+
end.create
|
97
|
+
assert_equal [:setup, :entity, :entity, :relationship, :save], executed_calls
|
98
|
+
end
|
99
|
+
|
100
|
+
test "create class method should return result of save" do
|
101
|
+
create_simple_domain
|
102
|
+
subclass = Class.new(Diagram) do
|
103
|
+
save do
|
104
|
+
"foobar"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
assert_equal "foobar", subclass.create
|
108
|
+
end
|
109
|
+
|
110
|
+
test "create should return result of save" do
|
111
|
+
create_simple_domain
|
112
|
+
diagram = Class.new(Diagram) do
|
113
|
+
save do
|
114
|
+
"foobar"
|
115
|
+
end
|
116
|
+
end.new(Domain.generate)
|
117
|
+
assert_equal "foobar", diagram.create
|
118
|
+
end
|
119
|
+
|
120
|
+
# Entity filtering =========================================================
|
121
|
+
test "generate should yield entities" do
|
122
|
+
create_model "Foo"
|
123
|
+
assert_equal [Foo], retrieve_entities.map(&:model)
|
124
|
+
end
|
125
|
+
|
126
|
+
test "generate should filter excluded entity" do
|
127
|
+
create_model "Book"
|
128
|
+
create_model "Author"
|
129
|
+
assert_equal [Book], retrieve_entities(:exclude => [:Author]).map(&:model)
|
130
|
+
end
|
131
|
+
|
132
|
+
test "generate should filter excluded entities" do
|
133
|
+
create_model "Book"
|
134
|
+
create_model "Author"
|
135
|
+
create_model "Editor"
|
136
|
+
assert_equal [Book], retrieve_entities(:exclude => [:Author, :Editor]).map(&:model)
|
137
|
+
end
|
138
|
+
|
139
|
+
test "generate should include only specified entity" do
|
140
|
+
create_model "Book"
|
141
|
+
create_model "Author"
|
142
|
+
assert_equal [Book], retrieve_entities(:only => [:Book]).map(&:model)
|
143
|
+
end
|
144
|
+
|
145
|
+
test "generate should include only specified entities" do
|
146
|
+
create_model "Book"
|
147
|
+
create_model "Author"
|
148
|
+
create_model "Editor"
|
149
|
+
assert_equal [Author, Editor], retrieve_entities(:only => [:Author, :Editor]).map(&:model)
|
150
|
+
end
|
151
|
+
|
152
|
+
test "generate should include only specified entities (With the class names as strings)" do
|
153
|
+
create_model "Book"
|
154
|
+
create_model "Author"
|
155
|
+
create_model "Editor"
|
156
|
+
assert_equal [Author, Editor], retrieve_entities(:only => ['Author', 'Editor']).map(&:model)
|
157
|
+
end
|
158
|
+
|
159
|
+
test "generate should filter disconnected entities if disconnected is false" do
|
160
|
+
create_model "Book", :author => :references do
|
161
|
+
belongs_to :author
|
162
|
+
end
|
163
|
+
create_model "Author"
|
164
|
+
create_model "Table", :type => :string
|
165
|
+
assert_equal [Author, Book], retrieve_entities(:disconnected => false).map(&:model)
|
166
|
+
end
|
167
|
+
|
168
|
+
test "generate should yield disconnected entities if disconnected is true" do
|
169
|
+
create_model "Foo", :type => :string
|
170
|
+
assert_equal [Foo], retrieve_entities(:disconnected => true).map(&:model)
|
171
|
+
end
|
172
|
+
|
173
|
+
test "generate should filter specialized entities" do
|
174
|
+
create_model "Foo", :type => :string
|
175
|
+
Object.const_set :SpecialFoo, Class.new(Foo)
|
176
|
+
assert_equal [Foo], retrieve_entities.map(&:model)
|
177
|
+
end
|
178
|
+
|
179
|
+
test "generate should yield specialized entities if inheritance is true" do
|
180
|
+
create_model "Foo", :type => :string
|
181
|
+
Object.const_set :SpecialFoo, Class.new(Foo)
|
182
|
+
assert_equal [Foo, SpecialFoo], retrieve_entities(:inheritance => true).map(&:model)
|
183
|
+
end
|
184
|
+
|
185
|
+
test "generate should yield specialized entities with distinct tables" do
|
186
|
+
create_model "Foo"
|
187
|
+
Object.const_set :SpecialFoo, Class.new(Foo)
|
188
|
+
SpecialFoo.class_eval do
|
189
|
+
self.table_name = "special_foo"
|
190
|
+
end
|
191
|
+
create_table "special_foo", {}, true
|
192
|
+
assert_equal [Foo, SpecialFoo], retrieve_entities.map(&:model)
|
193
|
+
end
|
194
|
+
|
195
|
+
test "generate should filter generalized entities" do
|
196
|
+
create_model "Cannon"
|
197
|
+
create_model "Galleon" do
|
198
|
+
has_many :cannons, :as => :defensible
|
199
|
+
end
|
200
|
+
assert_equal ["Cannon", "Galleon"], retrieve_entities.map(&:name)
|
201
|
+
end
|
202
|
+
|
203
|
+
test "generate should yield generalized entities if polymorphism is true" do
|
204
|
+
create_model "Cannon"
|
205
|
+
create_model "Galleon" do
|
206
|
+
has_many :cannons, :as => :defensible
|
207
|
+
end
|
208
|
+
assert_equal ["Cannon", "Defensible", "Galleon"], retrieve_entities(:polymorphism => true).map(&:name)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Relationship filtering ===================================================
|
212
|
+
test "generate should yield relationships" do
|
213
|
+
create_simple_domain
|
214
|
+
assert_equal 1, retrieve_relationships.length
|
215
|
+
end
|
216
|
+
|
217
|
+
test "generate should yield indirect relationships if indirect is true" do
|
218
|
+
create_model "Foo" do
|
219
|
+
has_many :bazs
|
220
|
+
has_many :bars
|
221
|
+
end
|
222
|
+
create_model "Bar", :foo => :references do
|
223
|
+
belongs_to :foo
|
224
|
+
has_many :bazs, :through => :foo
|
225
|
+
end
|
226
|
+
create_model "Baz", :foo => :references do
|
227
|
+
belongs_to :foo
|
228
|
+
end
|
229
|
+
assert_equal [false, false, true], retrieve_relationships(:indirect => true).map(&:indirect?)
|
230
|
+
end
|
231
|
+
|
232
|
+
test "generate should filter indirect relationships if indirect is false" do
|
233
|
+
create_model "Foo" do
|
234
|
+
has_many :bazs
|
235
|
+
has_many :bars
|
236
|
+
end
|
237
|
+
create_model "Bar", :foo => :references do
|
238
|
+
belongs_to :foo
|
239
|
+
has_many :bazs, :through => :foo
|
240
|
+
end
|
241
|
+
create_model "Baz", :foo => :references do
|
242
|
+
belongs_to :foo
|
243
|
+
end
|
244
|
+
assert_equal [false, false], retrieve_relationships(:indirect => false).map(&:indirect?)
|
245
|
+
end
|
246
|
+
|
247
|
+
test "generate should yield relationships from specialized entities" do
|
248
|
+
create_model "Foo", :bar => :references
|
249
|
+
create_model "Bar", :type => :string
|
250
|
+
Object.const_set :SpecialBar, Class.new(Bar)
|
251
|
+
SpecialBar.class_eval do
|
252
|
+
has_many :foos
|
253
|
+
end
|
254
|
+
assert_equal 1, retrieve_relationships.length
|
255
|
+
end
|
256
|
+
|
257
|
+
test "generate should yield relationships to specialized entities" do
|
258
|
+
create_model "Foo", :type => :string, :bar => :references
|
259
|
+
Object.const_set :SpecialFoo, Class.new(Foo)
|
260
|
+
create_model "Bar" do
|
261
|
+
has_many :special_foos
|
262
|
+
end
|
263
|
+
assert_equal 1, retrieve_relationships.length
|
264
|
+
end
|
265
|
+
|
266
|
+
# Specialization filtering =================================================
|
267
|
+
test "generate should not yield specializations" do
|
268
|
+
create_specialization
|
269
|
+
create_polymorphic_generalization
|
270
|
+
create_abstract_generalization
|
271
|
+
assert_equal [], retrieve_specializations
|
272
|
+
end
|
273
|
+
|
274
|
+
test "generate should yield specializations but not generalizations if inheritance is true" do
|
275
|
+
create_specialization
|
276
|
+
create_polymorphic_generalization
|
277
|
+
create_abstract_generalization
|
278
|
+
assert_equal ["Beer"], retrieve_specializations(:inheritance => true).map { |s| s.specialized.name }
|
279
|
+
end
|
280
|
+
|
281
|
+
test "generate should yield generalizations but not specializations if polymorphism is true" do
|
282
|
+
create_specialization
|
283
|
+
create_polymorphic_generalization
|
284
|
+
create_abstract_generalization
|
285
|
+
assert_equal ["Galleon", "Palace"], retrieve_specializations(:polymorphism => true).map { |s| s.specialized.name }
|
286
|
+
end
|
287
|
+
|
288
|
+
test "generate should yield specializations and generalizations if polymorphism and inheritance is true" do
|
289
|
+
create_specialization
|
290
|
+
create_polymorphic_generalization
|
291
|
+
create_abstract_generalization
|
292
|
+
assert_equal ["Beer", "Galleon", "Palace"], retrieve_specializations(:inheritance => true,
|
293
|
+
:polymorphism => true).map { |s| s.specialized.name }
|
294
|
+
end
|
295
|
+
|
296
|
+
# Attribute filtering ======================================================
|
297
|
+
test "generate should yield content attributes by default" do
|
298
|
+
create_model "Book", :title => :string, :created_at => :datetime, :author => :references do
|
299
|
+
belongs_to :author
|
300
|
+
end
|
301
|
+
create_model "Author"
|
302
|
+
assert_equal %w{title}, retrieve_attribute_lists[Book].map(&:name)
|
303
|
+
end
|
304
|
+
|
305
|
+
test "generate should yield primary key attributes if included" do
|
306
|
+
create_model "Book", :title => :string
|
307
|
+
create_model "Page", :book => :references do
|
308
|
+
belongs_to :book
|
309
|
+
end
|
310
|
+
assert_equal %w{id}, retrieve_attribute_lists(:attributes => [:primary_keys])[Book].map(&:name)
|
311
|
+
end
|
312
|
+
|
313
|
+
test "generate should yield [] if attributes = false" do
|
314
|
+
create_model "Book", :title => :string
|
315
|
+
create_model "Page", :book => :references do
|
316
|
+
belongs_to :book
|
317
|
+
end
|
318
|
+
assert_equal [], retrieve_attribute_lists(:attributes => [:false])[Book].map(&:name)
|
319
|
+
end
|
320
|
+
|
321
|
+
test "generate should yield foreign key attributes if included" do
|
322
|
+
create_model "Book", :author => :references do
|
323
|
+
belongs_to :author
|
324
|
+
end
|
325
|
+
create_model "Author"
|
326
|
+
assert_equal %w{author_id}, retrieve_attribute_lists(:attributes => [:foreign_keys])[Book].map(&:name)
|
327
|
+
end
|
328
|
+
|
329
|
+
test "generate should yield timestamp attributes if included" do
|
330
|
+
create_model "Book", :created_at => :datetime, :created_on => :date, :updated_at => :datetime, :updated_on => :date
|
331
|
+
create_model "Page", :book => :references do
|
332
|
+
belongs_to :book
|
333
|
+
end
|
334
|
+
assert_equal %w{created_at created_on updated_at updated_on},
|
335
|
+
retrieve_attribute_lists(:attributes => [:timestamps])[Book].map(&:name)
|
336
|
+
end
|
337
|
+
|
338
|
+
test "generate should yield combinations of attributes if included" do
|
339
|
+
create_model "Book", :created_at => :datetime, :title => :string, :author => :references do
|
340
|
+
belongs_to :author
|
341
|
+
end
|
342
|
+
create_model "Author"
|
343
|
+
assert_equal %w{created_at title},
|
344
|
+
retrieve_attribute_lists(:attributes => [:content, :timestamps])[Book].map(&:name)
|
345
|
+
end
|
346
|
+
|
347
|
+
test "generate should yield no attributes for specialized entities" do
|
348
|
+
create_model "Beverage", :type => :string, :name => :string, :distillery => :string, :age => :integer
|
349
|
+
Object.const_set :Whisky, Class.new(Beverage)
|
350
|
+
assert_equal [], retrieve_attribute_lists(:inheritance => true)[Whisky].map(&:name)
|
351
|
+
end
|
352
|
+
end
|