rails-erd 1.7.1 → 2.0.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.
- checksums.yaml +4 -4
- data/README.md +113 -17
- data/lib/generators/erd/install_generator.rb +2 -0
- data/lib/generators/erd/templates/auto_generate_diagram.rake +1 -1
- data/lib/rails-erd.rb +2 -0
- data/lib/rails_erd/cli.rb +48 -6
- data/lib/rails_erd/config.rb +7 -2
- data/lib/rails_erd/diagram/graphviz.rb +28 -15
- data/lib/rails_erd/diagram/mermaid.rb +152 -0
- data/lib/rails_erd/diagram/templates/node.html.erb +1 -1
- data/lib/rails_erd/diagram/templates/node.record.erb +2 -2
- data/lib/rails_erd/diagram.rb +5 -1
- data/lib/rails_erd/domain/attribute.rb +15 -5
- data/lib/rails_erd/domain/entity.rb +6 -0
- data/lib/rails_erd/domain/relationship/cardinality.rb +2 -0
- data/lib/rails_erd/domain/relationship.rb +2 -0
- data/lib/rails_erd/domain/specialization.rb +2 -0
- data/lib/rails_erd/domain.rb +66 -4
- data/lib/rails_erd/railtie.rb +3 -1
- data/lib/rails_erd/tasks.rake +24 -9
- data/lib/rails_erd/version.rb +3 -1
- data/lib/rails_erd.rb +7 -1
- data/test/support_files/erdconfig.empty +0 -0
- data/test/unit/cli_test.rb +75 -0
- data/test/unit/config_test.rb +7 -0
- data/test/unit/domain_test.rb +18 -13
- data/test/unit/graphviz_test.rb +11 -14
- data/test/unit/mermaid_test.rb +388 -0
- data/test/unit/rake_task_test.rb +23 -2
- metadata +36 -18
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
#--
|
|
4
4
|
module RailsERD
|
|
@@ -49,7 +49,7 @@ module RailsERD
|
|
|
49
49
|
# The type of the attribute, equal to the Rails migration type. Can be any
|
|
50
50
|
# of +:string+, +:integer+, +:boolean+, +:text+, etc.
|
|
51
51
|
def type
|
|
52
|
-
column.type or column.sql_type.downcase.to_sym
|
|
52
|
+
!RailsERD.options[:native_types] and column.type or column.sql_type.downcase.to_sym
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
# Returns +true+ if this attribute is a content column, that is, if it
|
|
@@ -77,9 +77,18 @@ module RailsERD
|
|
|
77
77
|
# Returns +true+ if this attribute is used as a foreign key for any
|
|
78
78
|
# relationship.
|
|
79
79
|
def foreign_key?
|
|
80
|
-
@domain
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
@domain
|
|
81
|
+
.relationships_by_entity_name(@model.name)
|
|
82
|
+
.map(&:associations)
|
|
83
|
+
.flatten
|
|
84
|
+
.map do |associaton|
|
|
85
|
+
result = associaton.send(Domain.foreign_key_method_name)
|
|
86
|
+
if result.respond_to?(:to_ary)
|
|
87
|
+
result.join("_").to_sym
|
|
88
|
+
else
|
|
89
|
+
result.to_sym
|
|
90
|
+
end
|
|
91
|
+
end.include?(name.to_sym)
|
|
83
92
|
end
|
|
84
93
|
|
|
85
94
|
# Returns +true+ if this attribute is used for single table inheritance.
|
|
@@ -120,6 +129,7 @@ module RailsERD
|
|
|
120
129
|
# <tt>:boolean, :null => false</tt>:: boolean *
|
|
121
130
|
def type_description
|
|
122
131
|
type.to_s.dup.tap do |desc|
|
|
132
|
+
desc << "[]" if column.respond_to?(:array?) && column.array?
|
|
123
133
|
desc << " #{limit_description}" if limit_description
|
|
124
134
|
desc << " ∗" if mandatory? && !primary_key? # Add a hair space + low asterisk (Unicode characters)
|
|
125
135
|
desc << " U" if unique? && !primary_key? && !foreign_key? # Add U if unique but non-key
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module RailsERD
|
|
2
4
|
class Domain
|
|
3
5
|
# Entities represent your Active Record models. Entities may be connected
|
|
@@ -38,6 +40,10 @@ module RailsERD
|
|
|
38
40
|
@domain, @name, @model = domain, name, model
|
|
39
41
|
end
|
|
40
42
|
|
|
43
|
+
def label
|
|
44
|
+
RailsERD.options[:table_names] ? model.table_name : name
|
|
45
|
+
end
|
|
46
|
+
|
|
41
47
|
# Returns an array of attributes for this entity.
|
|
42
48
|
def attributes
|
|
43
49
|
@attributes ||= generalized? ? [] : Attribute.from_model(domain, model)
|
data/lib/rails_erd/domain.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "rails_erd"
|
|
2
4
|
require "rails_erd/domain/attribute"
|
|
3
5
|
require "rails_erd/domain/entity"
|
|
@@ -65,7 +67,9 @@ module RailsERD
|
|
|
65
67
|
|
|
66
68
|
# Returns all relationships in your domain model.
|
|
67
69
|
def relationships
|
|
68
|
-
@relationships ||= Relationship.from_associations(self, associations)
|
|
70
|
+
@relationships ||= Relationship.from_associations(self, associations).select do |relationship|
|
|
71
|
+
relationship.source && relationship.destination
|
|
72
|
+
end
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
# Returns all specializations in your domain model.
|
|
@@ -120,7 +124,46 @@ module RailsERD
|
|
|
120
124
|
end
|
|
121
125
|
|
|
122
126
|
def models
|
|
123
|
-
@models ||= @source_models
|
|
127
|
+
@models ||= @source_models
|
|
128
|
+
.reject { |model| tableless_rails_models.include?(model) }
|
|
129
|
+
.select { |model| check_model_validity(model) }
|
|
130
|
+
.reject { |model| check_habtm_model(model) }
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Returns Rails model classes defined in the app
|
|
134
|
+
def rails_models
|
|
135
|
+
%w(
|
|
136
|
+
ActionMailbox::InboundEmail
|
|
137
|
+
ActionText::EncryptedRichText
|
|
138
|
+
ActionText::RichText
|
|
139
|
+
ActiveStorage::Attachment
|
|
140
|
+
ActiveStorage::Blob
|
|
141
|
+
ActiveStorage::VariantRecord
|
|
142
|
+
SolidCable::Message
|
|
143
|
+
SolidCache::Entry
|
|
144
|
+
SolidQueue::BlockedExecution
|
|
145
|
+
SolidQueue::ClaimedExecution
|
|
146
|
+
SolidQueue::Execution
|
|
147
|
+
SolidQueue::FailedExecution
|
|
148
|
+
SolidQueue::Job
|
|
149
|
+
SolidQueue::Pause
|
|
150
|
+
SolidQueue::Process
|
|
151
|
+
SolidQueue::ReadyExecution
|
|
152
|
+
SolidQueue::RecurringExecution
|
|
153
|
+
SolidQueue::RecurringTask
|
|
154
|
+
SolidQueue::ScheduledExecution
|
|
155
|
+
SolidQueue::Semaphore
|
|
156
|
+
).map { |model| Object.const_get(model) rescue nil }.compact
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def tableless_rails_models
|
|
160
|
+
@tableless_rails_models ||= begin
|
|
161
|
+
if defined? Rails
|
|
162
|
+
rails_models.reject{ |model| model.table_exists? }
|
|
163
|
+
else
|
|
164
|
+
[]
|
|
165
|
+
end
|
|
166
|
+
end
|
|
124
167
|
end
|
|
125
168
|
|
|
126
169
|
def associations
|
|
@@ -138,7 +181,13 @@ module RailsERD
|
|
|
138
181
|
raise "table #{model.table_name} does not exist"
|
|
139
182
|
end
|
|
140
183
|
rescue => e
|
|
141
|
-
warn "Ignoring invalid model #{model.name} (#{e.message})"
|
|
184
|
+
warn "Ignoring invalid model #{model.name} (#{e.message})" unless excluded_model?(model)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def excluded_model?(model)
|
|
188
|
+
return false unless options.exclude.present?
|
|
189
|
+
|
|
190
|
+
[options.exclude].flatten.map(&:to_sym).include?(model.name.to_sym)
|
|
142
191
|
end
|
|
143
192
|
|
|
144
193
|
def check_association_validity(association)
|
|
@@ -152,7 +201,20 @@ module RailsERD
|
|
|
152
201
|
entity_by_name(entity_name) or raise "model #{entity_name} exists, but is not included in domain"
|
|
153
202
|
end
|
|
154
203
|
rescue => e
|
|
155
|
-
warn "Ignoring invalid association #{association_description(association)} (#{e.message})"
|
|
204
|
+
warn "Ignoring invalid association #{association_description(association)} (#{e.message})" unless excluded_association?(association)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def excluded_association?(association)
|
|
208
|
+
return false unless options.exclude.present?
|
|
209
|
+
|
|
210
|
+
excluded_names = [options.exclude].flatten.map(&:to_sym)
|
|
211
|
+
|
|
212
|
+
# Suppress warning if either the source model or target model is excluded
|
|
213
|
+
excluded_names.include?(association.active_record.name.to_sym) ||
|
|
214
|
+
(association.klass.name && excluded_names.include?(association.klass.name.to_sym))
|
|
215
|
+
rescue NameError
|
|
216
|
+
# If we can't determine the target class, check only the source model
|
|
217
|
+
excluded_names.include?(association.active_record.name.to_sym)
|
|
156
218
|
end
|
|
157
219
|
|
|
158
220
|
def check_polymorphic_association_validity(association)
|
data/lib/rails_erd/railtie.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module RailsERD
|
|
2
|
-
# Rails ERD integrates with Rails
|
|
4
|
+
# Rails ERD integrates with Rails. If you add it to your +Gemfile+, you
|
|
3
5
|
# will gain a Rake task called +erd+, which you can use to generate diagrams
|
|
4
6
|
# of your domain model.
|
|
5
7
|
class Railtie < Rails::Railtie
|
data/lib/rails_erd/tasks.rake
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'graphviz/utils'
|
|
2
|
-
|
|
3
1
|
module ErdRakeHelper
|
|
4
2
|
def say(message)
|
|
5
3
|
puts message unless Rake.application.options.silent
|
|
@@ -8,10 +6,18 @@ end
|
|
|
8
6
|
|
|
9
7
|
namespace :erd do
|
|
10
8
|
task :check_dependencies do
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
if RailsERD.options.generator == :graphviz
|
|
10
|
+
begin
|
|
11
|
+
require 'graphviz/utils'
|
|
12
|
+
include GraphViz::Utils
|
|
13
|
+
unless find_executable("dot", nil)
|
|
14
|
+
raise "Unable to find GraphViz's \"dot\" executable. Please " \
|
|
15
|
+
"visit https://voormedia.github.io/rails-erd/install.html for installation instructions."
|
|
16
|
+
end
|
|
17
|
+
rescue LoadError
|
|
18
|
+
raise "The ruby-graphviz gem is required for Graphviz output. " \
|
|
19
|
+
"Add `gem 'ruby-graphviz'` to your Gemfile, or use `generator=mermaid` instead."
|
|
20
|
+
end
|
|
15
21
|
end
|
|
16
22
|
end
|
|
17
23
|
|
|
@@ -58,13 +64,22 @@ namespace :erd do
|
|
|
58
64
|
raise "Active Record was not loaded." unless defined? ActiveRecord
|
|
59
65
|
end
|
|
60
66
|
|
|
61
|
-
task :generate => [:
|
|
67
|
+
task :generate => [:options, :check_dependencies, :load_models] do
|
|
62
68
|
include ErdRakeHelper
|
|
63
69
|
|
|
64
70
|
say "Generating Entity-Relationship Diagram for #{ActiveRecord::Base.descendants.length} models..."
|
|
65
71
|
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
file = case RailsERD.options.generator
|
|
73
|
+
when :mermaid
|
|
74
|
+
require "rails_erd/diagram/mermaid"
|
|
75
|
+
RailsERD::Diagram::Mermaid.create
|
|
76
|
+
when :graphviz
|
|
77
|
+
require "rails_erd/diagram/graphviz"
|
|
78
|
+
RailsERD::Diagram::Graphviz.create
|
|
79
|
+
else
|
|
80
|
+
raise "Unknown generator: #{RailsERD.options.generator}"
|
|
81
|
+
end
|
|
82
|
+
|
|
68
83
|
|
|
69
84
|
say "Done! Saved diagram to ./#{file}"
|
|
70
85
|
end
|
data/lib/rails_erd/version.rb
CHANGED
data/lib/rails_erd.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "active_support/ordered_options"
|
|
2
4
|
require "rails_erd/railtie" if defined? Rails
|
|
3
5
|
require "rails_erd/config"
|
|
@@ -36,14 +38,16 @@ module RailsERD
|
|
|
36
38
|
|
|
37
39
|
def default_options
|
|
38
40
|
ActiveSupport::OrderedOptions[
|
|
41
|
+
:generator, :mermaid,
|
|
39
42
|
:attributes, :content,
|
|
40
43
|
:disconnected, true,
|
|
41
44
|
:filename, "erd",
|
|
42
|
-
:filetype, :
|
|
45
|
+
:filetype, :mmd,
|
|
43
46
|
:fonts, {},
|
|
44
47
|
:indirect, true,
|
|
45
48
|
:inheritance, false,
|
|
46
49
|
:markup, true,
|
|
50
|
+
:mermaid_style, :erdiagram,
|
|
47
51
|
:notation, :simple,
|
|
48
52
|
:orientation, :horizontal,
|
|
49
53
|
:polymorphism, false,
|
|
@@ -55,6 +59,8 @@ module RailsERD
|
|
|
55
59
|
:only_recursion_depth, nil,
|
|
56
60
|
:prepend_primary, false,
|
|
57
61
|
:cluster, false,
|
|
62
|
+
:table_names, false,
|
|
63
|
+
:native_types, false
|
|
58
64
|
]
|
|
59
65
|
end
|
|
60
66
|
|
|
File without changes
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
|
2
|
+
require "rails_erd/cli"
|
|
3
|
+
|
|
4
|
+
class CLITest < ActiveSupport::TestCase
|
|
5
|
+
def setup
|
|
6
|
+
RailsERD.options.filetype = :dot
|
|
7
|
+
RailsERD.options.warn = false
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Generator selection ========================================================
|
|
11
|
+
test "CLI should use mermaid generator by default" do
|
|
12
|
+
require "rails_erd/diagram/mermaid"
|
|
13
|
+
cli = RailsERD::CLI.new(Dir.pwd, {})
|
|
14
|
+
assert_equal RailsERD::Diagram::Mermaid, cli.send(:generator)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test "CLI should use graphviz generator when generator option is graphviz symbol" do
|
|
18
|
+
cli = RailsERD::CLI.new(Dir.pwd, { generator: :graphviz })
|
|
19
|
+
assert_equal RailsERD::Diagram::Graphviz, cli.send(:generator)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test "CLI should use mermaid generator when generator option is mermaid symbol" do
|
|
23
|
+
require "rails_erd/diagram/mermaid"
|
|
24
|
+
cli = RailsERD::CLI.new(Dir.pwd, { generator: :mermaid })
|
|
25
|
+
assert_equal RailsERD::Diagram::Mermaid, cli.send(:generator)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Option parsing (SYMBOL_OPTIONS conversion) =================================
|
|
29
|
+
test "CLI start should convert generator string to symbol" do
|
|
30
|
+
# Simulate what Choice.choices returns (strings)
|
|
31
|
+
Choice.stubs(:choices).returns({ "generator" => "mermaid" })
|
|
32
|
+
Choice.stubs(:rest).returns([])
|
|
33
|
+
|
|
34
|
+
# Capture the options passed to new
|
|
35
|
+
captured_options = nil
|
|
36
|
+
RailsERD::CLI.stubs(:new).with do |path, options|
|
|
37
|
+
captured_options = options
|
|
38
|
+
true
|
|
39
|
+
end.returns(stub(start: nil))
|
|
40
|
+
|
|
41
|
+
RailsERD::CLI.start
|
|
42
|
+
|
|
43
|
+
assert_equal :mermaid, captured_options[:generator]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
test "CLI start should convert mermaid_style string to symbol" do
|
|
47
|
+
Choice.stubs(:choices).returns({ "mermaid_style" => "erdiagram" })
|
|
48
|
+
Choice.stubs(:rest).returns([])
|
|
49
|
+
|
|
50
|
+
captured_options = nil
|
|
51
|
+
RailsERD::CLI.stubs(:new).with do |path, options|
|
|
52
|
+
captured_options = options
|
|
53
|
+
true
|
|
54
|
+
end.returns(stub(start: nil))
|
|
55
|
+
|
|
56
|
+
RailsERD::CLI.start
|
|
57
|
+
|
|
58
|
+
assert_equal :erdiagram, captured_options[:mermaid_style]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
test "CLI start should convert filetype string to symbol" do
|
|
62
|
+
Choice.stubs(:choices).returns({ "filetype" => "pdf" })
|
|
63
|
+
Choice.stubs(:rest).returns([])
|
|
64
|
+
|
|
65
|
+
captured_options = nil
|
|
66
|
+
RailsERD::CLI.stubs(:new).with do |path, options|
|
|
67
|
+
captured_options = options
|
|
68
|
+
true
|
|
69
|
+
end.returns(stub(start: nil))
|
|
70
|
+
|
|
71
|
+
RailsERD::CLI.start
|
|
72
|
+
|
|
73
|
+
assert_equal :pdf, captured_options[:filetype]
|
|
74
|
+
end
|
|
75
|
+
end
|
data/test/unit/config_test.rb
CHANGED
|
@@ -8,6 +8,13 @@ class ConfigTest < ActiveSupport::TestCase
|
|
|
8
8
|
assert_equal expected_hash, RailsERD::Config.load
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
test "load_config_file should return blank hash when config file is empty" do
|
|
12
|
+
set_local_config_file_to("erdconfig.empty")
|
|
13
|
+
|
|
14
|
+
expected_hash = {}
|
|
15
|
+
assert_equal expected_hash, RailsERD::Config.load
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
test "load_config_gile should return a hash from USER_WIDE_CONFIG_FILE when only USER_WIDE_CONFIG_FILE exists." do
|
|
12
19
|
set_user_config_file_to("erdconfig.example")
|
|
13
20
|
|
data/test/unit/domain_test.rb
CHANGED
|
@@ -127,21 +127,16 @@ class DomainTest < ActiveSupport::TestCase
|
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
test "relationships should count relationship between same models with distinct foreign key seperately" do
|
|
130
|
-
|
|
131
|
-
# :respond_to? check
|
|
132
|
-
#
|
|
133
|
-
if respond_to? :skip
|
|
134
|
-
skip("multiple edges between the same objects can cause segfaults in some versions of Graphviz")
|
|
130
|
+
skip("multiple edges between the same objects can cause segfaults in some versions of Graphviz")
|
|
135
131
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
assert_equal [Domain::Relationship] * 2, Domain.generate.relationships.collect(&:class)
|
|
132
|
+
create_model "Foo", :bar => :references, :special_bar => :references do
|
|
133
|
+
belongs_to :bar
|
|
134
|
+
end
|
|
135
|
+
create_model "Bar" do
|
|
136
|
+
has_many :foos, :foreign_key => :special_bar_id
|
|
144
137
|
end
|
|
138
|
+
|
|
139
|
+
assert_equal [Domain::Relationship] * 2, Domain.generate.relationships.collect(&:class)
|
|
145
140
|
end
|
|
146
141
|
|
|
147
142
|
test "relationships should use model name first in alphabet as source for many to many relationships" do
|
|
@@ -283,4 +278,14 @@ class DomainTest < ActiveSupport::TestCase
|
|
|
283
278
|
end
|
|
284
279
|
assert_match(/Ignoring invalid model Foo \(table foos does not exist\)/, output)
|
|
285
280
|
end
|
|
281
|
+
|
|
282
|
+
test "entities should not output a warning when a Rails model table does not exist" do
|
|
283
|
+
module ActionMailbox; end
|
|
284
|
+
|
|
285
|
+
Object.const_set :InboundEmail, ActionMailbox
|
|
286
|
+
output = collect_stdout do
|
|
287
|
+
Domain.generate.entities
|
|
288
|
+
end
|
|
289
|
+
assert_equal "", output
|
|
290
|
+
end
|
|
286
291
|
end
|
data/test/unit/graphviz_test.rb
CHANGED
|
@@ -193,7 +193,9 @@ class GraphvizTest < ActiveSupport::TestCase
|
|
|
193
193
|
|
|
194
194
|
test "generate should add set value for fontname attribute" do
|
|
195
195
|
create_simple_domain
|
|
196
|
-
|
|
196
|
+
# Use OS-appropriate font name (macOS uses PostScript names like "Arial BoldMT")
|
|
197
|
+
expected_font = RailsERD::Config.font_names_based_on_os[:bold]
|
|
198
|
+
assert_equal "\"#{expected_font}\"", diagram(fonts: {bold: expected_font}).graph.graph[:fontname].to_s
|
|
197
199
|
end
|
|
198
200
|
|
|
199
201
|
test "generate should add default value for splines attribute" do
|
|
@@ -314,21 +316,16 @@ class GraphvizTest < ActiveSupport::TestCase
|
|
|
314
316
|
end
|
|
315
317
|
|
|
316
318
|
test "generate should create edge for each relationship" do
|
|
317
|
-
|
|
318
|
-
# :respond_to? check
|
|
319
|
-
#
|
|
320
|
-
if respond_to? :skip
|
|
321
|
-
skip("multiple edges between the same objects can cause segfaults in some versions of Graphviz")
|
|
322
|
-
|
|
323
|
-
create_model "Foo", :bar => :references do
|
|
324
|
-
belongs_to :bar
|
|
325
|
-
end
|
|
326
|
-
create_model "Bar", :foo => :references do
|
|
327
|
-
belongs_to :foo
|
|
328
|
-
end
|
|
319
|
+
skip("multiple edges between the same objects can cause segfaults in some versions of Graphviz")
|
|
329
320
|
|
|
330
|
-
|
|
321
|
+
create_model "Foo", :bar => :references do
|
|
322
|
+
belongs_to :bar
|
|
323
|
+
end
|
|
324
|
+
create_model "Bar", :foo => :references do
|
|
325
|
+
belongs_to :foo
|
|
331
326
|
end
|
|
327
|
+
|
|
328
|
+
assert_equal [["m_Bar", "m_Foo"], ["m_Foo", "m_Bar"]], find_dot_node_pairs(diagram).sort
|
|
332
329
|
end
|
|
333
330
|
|
|
334
331
|
test "generate should create edge to polymorphic entity if polymorphism is true" do
|