rails-erd 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,7 +9,7 @@ class GraphvizTest < ActiveSupport::TestCase
9
9
 
10
10
  def teardown
11
11
  FileUtils.rm Dir["ERD.*"] rescue nil
12
- RailsERD::Diagram.send :remove_const, :Graphviz
12
+ RailsERD::Diagram.send :remove_const, :Graphviz rescue nil
13
13
  end
14
14
 
15
15
  def diagram(options = {})
@@ -148,6 +148,17 @@ class GraphvizTest < ActiveSupport::TestCase
148
148
  FileUtils.rm "foobar.png" rescue nil
149
149
  end
150
150
  end
151
+
152
+ test "create should abort and complain if output directory does not exist" do
153
+ message = nil
154
+ begin
155
+ create_simple_domain
156
+ Diagram::Graphviz.create :filename => "does_not_exist/foo"
157
+ rescue => e
158
+ message = e.message
159
+ end
160
+ assert_match /Output directory 'does_not_exist' does not exist/, message
161
+ end
151
162
 
152
163
  # Graphviz output ==========================================================
153
164
  test "generate should create directed graph" do
@@ -208,7 +219,7 @@ class GraphvizTest < ActiveSupport::TestCase
208
219
  create_model "Lid", :jar => :references do
209
220
  belongs_to :jar
210
221
  end
211
- assert_not_match %r{contents}, find_dot_node(diagram(:attributes => false), "Jar")[:label].to_gv
222
+ assert_no_match %r{contents}, find_dot_node(diagram(:attributes => false), "Jar")[:label].to_gv
212
223
  end
213
224
 
214
225
  test "generate should create edge for each relationship" do
@@ -237,6 +248,33 @@ class GraphvizTest < ActiveSupport::TestCase
237
248
  assert_match %r(\A<\s*<.*\|.*>\s*>\Z)m, find_dot_node(diagram(:orientation => :horizontal), "Author")[:label].to_gv
238
249
  end
239
250
 
251
+ test "generate should create edge to generalized entity if polymorphism is true" do
252
+ create_model "Cannon", :defensible => :references do
253
+ belongs_to :defensible, :polymorphic => true
254
+ end
255
+ create_model "Stronghold" do
256
+ has_many :cannons, :as => :defensible
257
+ end
258
+ create_model "Galleon" do
259
+ has_many :cannons, :as => :defensible
260
+ end
261
+ assert_equal [["Defensible", "Cannon"], ["Defensible", "Galleon"], ["Defensible", "Stronghold"]],
262
+ find_dot_node_pairs(diagram(:polymorphism => true)).sort
263
+ end
264
+
265
+ test "generate should create edge to each child of generalized entity if polymorphism is false" do
266
+ create_model "Cannon", :defensible => :references do
267
+ belongs_to :defensible, :polymorphic => true
268
+ end
269
+ create_model "Stronghold" do
270
+ has_many :cannons, :as => :defensible
271
+ end
272
+ create_model "Galleon" do
273
+ has_many :cannons, :as => :defensible
274
+ end
275
+ assert_equal [["Galleon", "Cannon"], ["Stronghold", "Cannon"]], find_dot_node_pairs(diagram).sort
276
+ end
277
+
240
278
  # Simple notation style ====================================================
241
279
  test "generate should use no style for one to one cardinalities with simple notation" do
242
280
  create_one_to_one_assoc_domain
@@ -254,38 +292,38 @@ class GraphvizTest < ActiveSupport::TestCase
254
292
  end
255
293
 
256
294
  # Advanced notation style ===================================================
257
- test "generate should use open dots for one to one cardinalities with advanced notation" do
295
+ test "generate should use open dots for one to one cardinalities with bachman notation" do
258
296
  create_one_to_one_assoc_domain
259
- assert_equal [["odot", "odot"]], find_dot_edge_styles(diagram(:notation => :advanced))
297
+ assert_equal [["odot", "odot"]], find_dot_edge_styles(diagram(:notation => :bachman))
260
298
  end
261
299
 
262
- test "generate should use dots for mandatory one to one cardinalities with advanced notation" do
300
+ test "generate should use dots for mandatory one to one cardinalities with bachman notation" do
263
301
  create_one_to_one_assoc_domain
264
302
  One.class_eval do
265
303
  validates_presence_of :other
266
304
  end
267
- assert_equal [["odot", "dot"]], find_dot_edge_styles(diagram(:notation => :advanced))
305
+ assert_equal [["dot", "odot"]], find_dot_edge_styles(diagram(:notation => :bachman))
268
306
  end
269
307
 
270
- test "generate should use normal arrow and open dot head with dot tail for one to many cardinalities with advanced notation" do
308
+ test "generate should use normal arrow and open dot head with dot tail for one to many cardinalities with bachman notation" do
271
309
  create_one_to_many_assoc_domain
272
- assert_equal [["odot", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :advanced))
310
+ assert_equal [["odot", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
273
311
  end
274
312
 
275
- test "generate should use normal arrow and dot head for mandatory one to many cardinalities with advanced notation" do
313
+ test "generate should use normal arrow and dot head for mandatory one to many cardinalities with bachman notation" do
276
314
  create_one_to_many_assoc_domain
277
315
  One.class_eval do
278
316
  validates_presence_of :many
279
317
  end
280
- assert_equal [["odot", "dotnormal"]], find_dot_edge_styles(diagram(:notation => :advanced))
318
+ assert_equal [["dot", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
281
319
  end
282
320
 
283
- test "generate should use normal arrow and open dot head and tail for many to many cardinalities with advanced notation" do
321
+ test "generate should use normal arrow and open dot head and tail for many to many cardinalities with bachman notation" do
284
322
  create_many_to_many_assoc_domain
285
- assert_equal [["odotnormal", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :advanced))
323
+ assert_equal [["odotnormal", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
286
324
  end
287
325
 
288
- test "generate should use normal arrow and dot tail and head for mandatory many to many cardinalities with advanced notation" do
326
+ test "generate should use normal arrow and dot tail and head for mandatory many to many cardinalities with bachman notation" do
289
327
  create_many_to_many_assoc_domain
290
328
  Many.class_eval do
291
329
  validates_presence_of :more
@@ -293,6 +331,6 @@ class GraphvizTest < ActiveSupport::TestCase
293
331
  More.class_eval do
294
332
  validates_presence_of :many
295
333
  end
296
- assert_equal [["dotnormal", "dotnormal"]], find_dot_edge_styles(diagram(:notation => :advanced))
334
+ assert_equal [["dotnormal", "dotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
297
335
  end
298
336
  end
@@ -67,8 +67,8 @@ class RakeTaskTest < ActiveSupport::TestCase
67
67
  end
68
68
 
69
69
  test "options task should set known array command line options" do
70
- ENV["attributes"] = "regular,timestamps"
70
+ ENV["attributes"] = "content,timestamps"
71
71
  Rake::Task["erd:options"].execute
72
- assert_equal [:regular, :timestamps], RailsERD.options.attributes
72
+ assert_equal [:content, :timestamps], RailsERD.options.attributes
73
73
  end
74
74
  end
@@ -1,7 +1,7 @@
1
1
  require File.expand_path("../test_helper", File.dirname(__FILE__))
2
2
 
3
3
  class RelationshipTest < ActiveSupport::TestCase
4
- N = Relationship::N
4
+ N = Domain::Relationship::N
5
5
 
6
6
  def domain_cardinalities
7
7
  Domain.generate.relationships.map(&:cardinality)
@@ -13,7 +13,7 @@ class RelationshipTest < ActiveSupport::TestCase
13
13
  belongs_to :bar
14
14
  end
15
15
  create_model "Bar"
16
- assert_match %r{#<RailsERD::Relationship:.* @source=Bar @destination=Foo>}, Domain.generate.relationships.first.inspect
16
+ assert_match %r{#<RailsERD::Domain::Relationship:.* @source=Bar @destination=Foo>}, Domain.generate.relationships.first.inspect
17
17
  end
18
18
 
19
19
  test "source should return relationship source" do
@@ -22,7 +22,7 @@ class RelationshipTest < ActiveSupport::TestCase
22
22
  end
23
23
  create_model "Bar"
24
24
  domain = Domain.generate
25
- assert_equal [domain.entity_for(Bar)], domain.relationships.map(&:source)
25
+ assert_equal [domain.entity_by_name("Bar")], domain.relationships.map(&:source)
26
26
  end
27
27
 
28
28
  test "destination should return relationship destination" do
@@ -31,7 +31,7 @@ class RelationshipTest < ActiveSupport::TestCase
31
31
  end
32
32
  create_model "Bar"
33
33
  domain = Domain.generate
34
- assert_equal [domain.entity_for(Foo)], domain.relationships.map(&:destination)
34
+ assert_equal [domain.entity_by_name("Foo")], domain.relationships.map(&:destination)
35
35
  end
36
36
 
37
37
  # Relationship properties ==================================================
@@ -138,11 +138,24 @@ class RelationshipTest < ActiveSupport::TestCase
138
138
  end
139
139
  assert_equal [4], Domain.generate.relationships.map(&:strength)
140
140
  end
141
+
142
+ test "strength should count polymorphic associations only once" do
143
+ create_model "Foo", :bar => :references do
144
+ belongs_to :bar, :polymorphic => true
145
+ end
146
+ create_model "Qux" do
147
+ has_many :foos, :as => :bar
148
+ end
149
+ create_model "Quux" do
150
+ has_many :foos, :as => :bar
151
+ end
152
+ assert_equal [1], Domain.generate.relationships.map(&:strength)
153
+ end
141
154
 
142
155
  # Cardinalities ============================================================
143
156
  test "cardinality should be zero-one to zero-one for optional one to one associations" do
144
157
  create_one_to_one_assoc_domain
145
- assert_equal [Relationship::Cardinality.new(0..1, 0..1)], domain_cardinalities
158
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 0..1)], domain_cardinalities
146
159
  end
147
160
 
148
161
  test "cardinality should be one to one for mutually mandatory one to one associations" do
@@ -153,12 +166,12 @@ class RelationshipTest < ActiveSupport::TestCase
153
166
  Other.class_eval do
154
167
  validates_presence_of :one
155
168
  end
156
- assert_equal [Relationship::Cardinality.new(1, 1)], domain_cardinalities
169
+ assert_equal [Domain::Relationship::Cardinality.new(1, 1)], domain_cardinalities
157
170
  end
158
171
 
159
172
  test "cardinality should be zero-one to zero-many for optional one to many associations" do
160
173
  create_one_to_many_assoc_domain
161
- assert_equal [Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
174
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
162
175
  end
163
176
 
164
177
  test "cardinality should be one to zero-many for one to many associations with not null foreign key" do
@@ -169,7 +182,7 @@ class RelationshipTest < ActiveSupport::TestCase
169
182
  belongs_to :one
170
183
  end
171
184
  add_column :manies, :one_id, :integer, :null => false, :default => 0
172
- assert_equal [Relationship::Cardinality.new(1, 0..N)], domain_cardinalities
185
+ assert_equal [Domain::Relationship::Cardinality.new(1, 0..N)], domain_cardinalities
173
186
  end
174
187
 
175
188
  test "cardinality should be one to one-many for mutually mandatory one to many associations" do
@@ -180,7 +193,7 @@ class RelationshipTest < ActiveSupport::TestCase
180
193
  Many.class_eval do
181
194
  validates_presence_of :one
182
195
  end
183
- assert_equal [Relationship::Cardinality.new(1, 1..N)], domain_cardinalities
196
+ assert_equal [Domain::Relationship::Cardinality.new(1, 1..N)], domain_cardinalities
184
197
  end
185
198
 
186
199
  test "cardinality should be zero-one to one-n for maximised one to many associations" do
@@ -192,7 +205,7 @@ class RelationshipTest < ActiveSupport::TestCase
192
205
  validates_length_of :many, :maximum => 5
193
206
  validates_length_of :many, :maximum => 2 # The lowest maximum should be used.
194
207
  end
195
- assert_equal [Relationship::Cardinality.new(0..1, 1..2)], domain_cardinalities
208
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 1..2)], domain_cardinalities
196
209
  end
197
210
 
198
211
  test "cardinality should be zero-one to n-many for minimised one to many associations" do
@@ -202,7 +215,7 @@ class RelationshipTest < ActiveSupport::TestCase
202
215
  validates_length_of :many, :minimum => 2
203
216
  validates_length_of :many, :minimum => 5 # The highest minimum should be used.
204
217
  end
205
- assert_equal [Relationship::Cardinality.new(0..1, 5..N)], domain_cardinalities
218
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 5..N)], domain_cardinalities
206
219
  end
207
220
 
208
221
  test "cardinality should be zero-one to n-m for limited one to many associations with single validation" do
@@ -210,7 +223,7 @@ class RelationshipTest < ActiveSupport::TestCase
210
223
  One.class_eval do
211
224
  validates_length_of :many, :minimum => 5, :maximum => 17
212
225
  end
213
- assert_equal [Relationship::Cardinality.new(0..1, 5..17)], domain_cardinalities
226
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 5..17)], domain_cardinalities
214
227
  end
215
228
 
216
229
  test "cardinality should be zero-one to n-m for limited one to many associations with multiple validations" do
@@ -221,12 +234,12 @@ class RelationshipTest < ActiveSupport::TestCase
221
234
  validates_length_of :many, :minimum => 5
222
235
  validates_length_of :many, :minimum => 2, :maximum => 28
223
236
  end
224
- assert_equal [Relationship::Cardinality.new(0..1, 5..17)], domain_cardinalities
237
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 5..17)], domain_cardinalities
225
238
  end
226
239
 
227
240
  test "cardinality should be zero-many to zero-many for optional many to many associations" do
228
241
  create_many_to_many_assoc_domain
229
- assert_equal [Relationship::Cardinality.new(0..N, 0..N)], domain_cardinalities
242
+ assert_equal [Domain::Relationship::Cardinality.new(0..N, 0..N)], domain_cardinalities
230
243
  end
231
244
 
232
245
  test "cardinality should be one-many to one-many for mutually mandatory many to many associations" do
@@ -237,7 +250,7 @@ class RelationshipTest < ActiveSupport::TestCase
237
250
  More.class_eval do
238
251
  validates_presence_of :many
239
252
  end
240
- assert_equal [Relationship::Cardinality.new(1..N, 1..N)], domain_cardinalities
253
+ assert_equal [Domain::Relationship::Cardinality.new(1..N, 1..N)], domain_cardinalities
241
254
  end
242
255
 
243
256
  test "cardinality should be n-m to n-m for limited many to many associations with single validations" do
@@ -248,7 +261,7 @@ class RelationshipTest < ActiveSupport::TestCase
248
261
  More.class_eval do
249
262
  validates_length_of :many, :maximum => 29, :minimum => 7
250
263
  end
251
- assert_equal [Relationship::Cardinality.new(3..18, 7..29)], domain_cardinalities
264
+ assert_equal [Domain::Relationship::Cardinality.new(3..18, 7..29)], domain_cardinalities
252
265
  end
253
266
 
254
267
  test "cardinality should be n-m to n-m for limited many to many associations with multiple validations" do
@@ -265,7 +278,7 @@ class RelationshipTest < ActiveSupport::TestCase
265
278
  validates_length_of :many, :minimum => 9
266
279
  validates_length_of :many, :maximum => 17
267
280
  end
268
- assert_equal [Relationship::Cardinality.new(3..20, 9..17)], domain_cardinalities
281
+ assert_equal [Domain::Relationship::Cardinality.new(3..20, 9..17)], domain_cardinalities
269
282
  end
270
283
 
271
284
  # Cardinality for non-mutual relationships =================================
@@ -274,7 +287,7 @@ class RelationshipTest < ActiveSupport::TestCase
274
287
  create_model "Many", :one => :references do
275
288
  belongs_to :one
276
289
  end
277
- assert_equal [Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
290
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
278
291
  end
279
292
 
280
293
  test "cardinality should be zero-one to zero-many for non mutual relationship with has_many association" do
@@ -282,7 +295,7 @@ class RelationshipTest < ActiveSupport::TestCase
282
295
  has_many :many
283
296
  end
284
297
  create_model "Many", :one => :references
285
- assert_equal [Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
298
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
286
299
  end
287
300
 
288
301
  test "cardinality should be zero-one to zero-one for non mutual relationship with has_one association" do
@@ -290,7 +303,7 @@ class RelationshipTest < ActiveSupport::TestCase
290
303
  has_one :other
291
304
  end
292
305
  create_model "Other", :one => :references
293
- assert_equal [Relationship::Cardinality.new(0..1, 0..1)], domain_cardinalities
306
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 0..1)], domain_cardinalities
294
307
  end
295
308
 
296
309
  test "cardinality should be zero-many to zero-many for non mutual relationship with has_and_belongs_to_many association" do
@@ -299,7 +312,7 @@ class RelationshipTest < ActiveSupport::TestCase
299
312
  create_model "More" do
300
313
  has_and_belongs_to_many :many
301
314
  end
302
- assert_equal [Relationship::Cardinality.new(0..N, 0..N)], domain_cardinalities
315
+ assert_equal [Domain::Relationship::Cardinality.new(0..N, 0..N)], domain_cardinalities
303
316
  end
304
317
 
305
318
  # Cardinality for multiple associations ====================================
@@ -314,7 +327,7 @@ class RelationshipTest < ActiveSupport::TestCase
314
327
  # many cards. The association has an infinite maximum cardinality.
315
328
  has_one :preferred_credit_card, :class_name => "CreditCard"
316
329
  end
317
- assert_equal [Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
330
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 0..N)], domain_cardinalities
318
331
  end
319
332
 
320
333
  test "cardinality should be zero-one to one-many for conflicting validations in one to many associations" do
@@ -329,7 +342,7 @@ class RelationshipTest < ActiveSupport::TestCase
329
342
  # minimum cardinality of one.
330
343
  validates_presence_of :books
331
344
  end
332
- assert_equal [Relationship::Cardinality.new(0..1, 1..N)], domain_cardinalities
345
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 1..N)], domain_cardinalities
333
346
  end
334
347
 
335
348
  test "cardinality should be n-m to n-m for conflicting validations in one to many associations" do
@@ -345,7 +358,23 @@ class RelationshipTest < ActiveSupport::TestCase
345
358
  validates_length_of :ice_spells, :in => 10..20
346
359
  validates_length_of :fire_spells, :in => 50..100
347
360
  end
348
- assert_equal [Relationship::Cardinality.new(0..1, 50..100)], domain_cardinalities
361
+ assert_equal [Domain::Relationship::Cardinality.new(0..1, 50..100)], domain_cardinalities
362
+ end
363
+
364
+ test "cardinality should be one to one-many for mandatory one to many associations on polymorphic interfaces" do
365
+ create_model "Cannon", :defensible => :references do
366
+ belongs_to :defensible, :polymorphic => true
367
+ validates_presence_of :defensible
368
+ end
369
+ create_model "Stronghold" do
370
+ has_many :cannons, :as => :defensible
371
+ validates_presence_of :cannons
372
+ end
373
+ create_model "Galleon" do
374
+ has_many :cannons, :as => :defensible
375
+ validates_presence_of :cannons
376
+ end
377
+ assert_equal [Domain::Relationship::Cardinality.new(1, 1..N)], domain_cardinalities
349
378
  end
350
379
 
351
380
  # Cardinality classes ======================================================
@@ -415,4 +444,24 @@ class RelationshipTest < ActiveSupport::TestCase
415
444
  domain = Domain.generate
416
445
  assert_equal [:one_to_many], domain.relationships.map(&:cardinality).map(&:name)
417
446
  end
447
+
448
+ test "cardinality should be one to many for has_many associations from generalized entity" do
449
+ create_model "Stronghold" do
450
+ has_many :cannons, :as => :defensible
451
+ end
452
+ create_model "Cannon", :defensible => :references do
453
+ belongs_to :defensible, :polymorphic => true
454
+ end
455
+ domain = Domain.generate
456
+
457
+ assert_equal [:one_to_many], domain.relationships.map(&:cardinality).map(&:name)
458
+ assert_equal [false], domain.relationships.map(&:one_to_one?)
459
+ assert_equal [true], domain.relationships.map(&:one_to_many?)
460
+ assert_equal [false], domain.relationships.map(&:many_to_many?)
461
+
462
+ assert_equal [true], domain.relationships.map(&:one_to?)
463
+ assert_equal [false], domain.relationships.map(&:many_to?)
464
+ assert_equal [false], domain.relationships.map(&:to_one?)
465
+ assert_equal [true], domain.relationships.map(&:to_many?)
466
+ end
418
467
  end
@@ -0,0 +1,57 @@
1
+ require File.expand_path("../test_helper", File.dirname(__FILE__))
2
+
3
+ class SpecializationTest < ActiveSupport::TestCase
4
+ # Specialization ===========================================================
5
+ test "inspect should show source and destination" do
6
+ create_specialization
7
+ domain = Domain.generate
8
+ assert_match %r{#<RailsERD::Domain::Specialization:.* @generalized=Beverage @specialized=Beer>},
9
+ Domain::Specialization.new(domain, domain.entity_by_name("Beverage"), domain.entity_by_name("Beer")).inspect
10
+ end
11
+
12
+ test "generalized should return source entity" do
13
+ create_specialization
14
+ domain = Domain.generate
15
+ assert_equal domain.entity_by_name("Beverage"),
16
+ Domain::Specialization.new(domain, domain.entity_by_name("Beverage"), domain.entity_by_name("Beer")).generalized
17
+ end
18
+
19
+ test "specialized should return destination entity" do
20
+ create_specialization
21
+ domain = Domain.generate
22
+ assert_equal domain.entity_by_name("Beer"),
23
+ Domain::Specialization.new(domain, domain.entity_by_name("Beverage"), domain.entity_by_name("Beer")).specialized
24
+ end
25
+
26
+ # Specialization properties ================================================
27
+ test "inheritance should be true for inheritance specializations" do
28
+ create_specialization
29
+ assert_equal [true], Domain.generate.specializations.map(&:inheritance?)
30
+ end
31
+
32
+ test "polymorphic should be false for inheritance specializations" do
33
+ create_specialization
34
+ assert_equal [false], Domain.generate.specializations.map(&:polymorphic?)
35
+ end
36
+
37
+ test "inheritance should be false for polymorphic specializations" do
38
+ create_generalization
39
+ assert_equal [false], Domain.generate.specializations.map(&:inheritance?)
40
+ end
41
+
42
+ test "polymorphic should be true for polymorphic specializations" do
43
+ create_generalization
44
+ assert_equal [true], Domain.generate.specializations.map(&:polymorphic?)
45
+ end
46
+
47
+ test "inheritance should be false for polymorphic specializations to specialized entities" do
48
+ create_model "Cannon"
49
+ create_model "Ship", :type => :string
50
+ create_model "Galleon", Ship do
51
+ has_many :cannons, :as => :defensible
52
+ end
53
+ domain = Domain.generate
54
+ assert_equal false, domain.specializations.find { |s|
55
+ s.generalized == domain.entity_by_name("Defensible") }.inheritance?
56
+ end
57
+ end