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.
@@ -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. See the README.rdoc file for more information.
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.3.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-03}
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.rdoc"
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.rdoc",
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/entity.rb",
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.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.17"])
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.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.17"])
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.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.17"])
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, columns = {}, &block)
37
- klass = Object.const_set name.to_sym, Class.new(ActiveRecord::Base)
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
- create_table Object.const_get(name.to_sym).table_name, columns, Object.const_get(name.to_sym).primary_key rescue nil
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
@@ -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.arel_table.attributes[name].column)
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.arel_table.attributes["my_column"].column,
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 = Attribute.new(Domain.new, Foo, Foo.arel_table.attributes["a"].column)
36
- b = Attribute.new(Domain.new, Foo, Foo.arel_table.attributes["b"].column)
37
- c = Attribute.new(Domain.new, Foo, Foo.arel_table.attributes["c"].column)
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:.* @column="my_column" @type=:string>},
44
- Attribute.new(Domain.new, Foo, Foo.arel_table.attributes["my_column"].column).inspect
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
@@ -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
- define_method :process_relationship do |relationship|
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 retrieve_entities(options = {})
35
+
36
+ def retrieve_specializations(options = {})
25
37
  klass = Class.new(Diagram)
26
- [].tap do |entities|
38
+ [].tap do |specializations|
27
39
  klass.class_eval do
28
- define_method :process_entity do |entity, attributes|
29
- entities << entity
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
- define_method :process_entity do |entity, attributes|
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
- def save
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
- def save
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 descendant entities" do
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 descended entities with distinct tables" do
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 filter relationships from descendant entities" do
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 [], retrieve_relationships
228
+ assert_equal 1, retrieve_relationships.length
174
229
  end
175
230
 
176
- test "generate should filter relationships to descendant entities" do
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 [], retrieve_relationships
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 regular attributes by default" do
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 => [:regular, :timestamps])[Book].map(&:name)
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