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.
@@ -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