rails-erd 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  doc
2
2
  pkg
3
3
  rdoc
4
+ *.rbc
5
+ .yardoc
data/CHANGES.rdoc CHANGED
@@ -1,3 +1,13 @@
1
+ === 0.2.0
2
+
3
+ * Added simple way to create your own type of diagrams with a tiny amount of
4
+ code.
5
+ * Improved internal API and documentation.
6
+ * Subtle changes in diagram style.
7
+ * Fixed error where non-mutual relationships might be inadvertently classified
8
+ as indirect relationships.
9
+ * Fixed error where diagrams with a vertical layout might fail to be generated.
10
+
1
11
  === 0.1.1
2
12
 
3
13
  * Fixed small errors in Ruby 1.8.7.
data/README.rdoc CHANGED
@@ -40,7 +40,6 @@ http://rails-erd.rubyforge.org/examples/typo-blog.png
40
40
 
41
41
  {Download complete diagram as PDF}[http://rails-erd.rubyforge.org/examples/typo-blog.pdf]
42
42
 
43
-
44
43
  == Getting started
45
44
 
46
45
  In its most simple form, Rails ERD is a plugin for Rails 3 that provides you
@@ -102,7 +101,56 @@ suppress_warnings:: When set to +true+, no warnings are printed to the
102
101
  command line while processing the domain model. Defaults
103
102
  to +false+.
104
103
 
105
- == Advanced use
104
+ == Custom diagrams
105
+
106
+ If you're completely unsatisfied with the diagrams that Rails ERD creates,
107
+ you can still use it to create your own diagrams. It provides you with an easy
108
+ way to create any kind of diagram based on your application's domain model.
109
+
110
+ As an example, a diagram class that generates code that can be used with
111
+ yUML (http://yuml.me) can be as simple as:
112
+
113
+ require "rails_erd/diagram"
114
+
115
+ class YumlDiagram < RailsERD::Diagram
116
+ def process_relationship(rel)
117
+ return if rel.indirect?
118
+
119
+ arrow = case
120
+ when rel.cardinality.one_to_one? then "1-1>"
121
+ when rel.cardinality.one_to_many? then "1-*>"
122
+ when rel.cardinality.many_to_many? then "*-*>"
123
+ end
124
+
125
+ instructions << "[#{rel.source}] #{arrow} [#{rel.destination}]"
126
+ end
127
+
128
+ def save
129
+ instructions * "\n"
130
+ end
131
+
132
+ def instructions
133
+ @instructions ||= []
134
+ end
135
+ end
136
+
137
+ Only 18 lines of code! Then, to generate the diagram (example based on the
138
+ domain model of Gemcutter):
139
+
140
+ YumlDiagram.create
141
+ #=> "[Rubygem] 1-*> [Ownership]
142
+ # [Rubygem] 1-*> [Subscription]
143
+ # [Rubygem] 1-*> [Version]
144
+ # [Rubygem] 1-1> [Linkset]
145
+ # [Rubygem] 1-*> [Dependency]
146
+ # [Version] 1-*> [Dependency]
147
+ # [User] 1-*> [Ownership]
148
+ # [User] 1-*> [Subscription]
149
+ # [User] 1-*> [WebHook]"
150
+
151
+ {See what that would look like}[http://yuml.me/diagram/scruffy/class/%5BRubygem%5D%201-*%3E%20%5BOwnership%5D,%20%5BRubygem%5D%201-*%3E%20%5BSubscription%5D,%20%5BRubygem%5D%201-*%3E%20%5BVersion%5D,%20%5BRubygem%5D%201-1%3E%20%5BLinkset%5D,%20%5BRubygem%5D%201-*%3E%20%5BDependency%5D,%20%5BVersion%5D%201-*%3E%20%5BDependency%5D,%20%5BUser%5D%201-*%3E%20%5BOwnership%5D,%20%5BUser%5D%201-*%3E%20%5BSubscription%5D,%20%5BUser%5D%201-*%3E%20%5BWebHook%5D].
152
+
153
+ == Internal API
106
154
 
107
155
  Rails ERD also allows you to use its internal API to inspect your Rails domain
108
156
  model. It is easy to generate alternative presentations of your Active Record
@@ -158,10 +206,6 @@ The above is just a sample of what is possible. See the API documentation for
158
206
  more details:
159
207
  http://rails-erd.rubyforge.org/doc/
160
208
 
161
- If you wish to generate your own graphs, take a look at how the default
162
- diagrams are being generated. See the source of RailsERD::Diagram:
163
- http://github.com/voormedia/rails-erd/blob/master/lib/rails_erd/diagram.rb
164
-
165
209
  Please note that before the 1.0 release, the API may change subtly between
166
210
  minor versions.
167
211
 
data/Rakefile CHANGED
@@ -12,8 +12,10 @@ Jeweler::Tasks.new do |spec|
12
12
  spec.email = "r.timmermans@voormedia.com"
13
13
  spec.homepage = "http://rails-erd.rubyforge.org/"
14
14
 
15
+ spec.add_runtime_dependency "activerecord", "~> 3.0.0"
15
16
  spec.add_runtime_dependency "activesupport", "~> 3.0.0"
16
17
  spec.add_runtime_dependency "ruby-graphviz", "~> 0.9.17"
18
+ spec.add_development_dependency "sqlite3-ruby"
17
19
  end
18
20
 
19
21
  Jeweler::GemcutterTasks.new
@@ -36,6 +38,5 @@ begin
36
38
  rdoc.title = "Rails ERD – Entity-Relationship Diagrams for Rails"
37
39
  rdoc.rdoc_dir = "rdoc"
38
40
  end
39
- rescue => e
40
- puts e.message
41
+ rescue LoadError
41
42
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
@@ -3,17 +3,17 @@ module RailsERD
3
3
  # Describes an entity's attribute. Attributes correspond directly to
4
4
  # database columns.
5
5
  class Attribute
6
- TIMESTAMP_NAMES = %w{created_at created_on updated_at updated_on} #:nodoc:
6
+ TIMESTAMP_NAMES = %w{created_at created_on updated_at updated_on} # @private :nodoc:
7
7
 
8
8
  class << self
9
- def from_model(domain, model) #:nodoc:
9
+ def from_model(domain, model) # @private :nodoc:
10
10
  model.arel_table.columns.collect { |column| Attribute.new(domain, model, column) }.sort
11
11
  end
12
12
  end
13
13
 
14
- attr_reader :column #:nodoc:
14
+ attr_reader :column # @private :nodoc:
15
15
 
16
- def initialize(domain, model, column) #:nodoc:
16
+ def initialize(domain, model, column) # @private :nodoc:
17
17
  @domain, @model, @column = domain, model, column
18
18
  end
19
19
 
@@ -53,15 +53,15 @@ module RailsERD
53
53
  TIMESTAMP_NAMES.include? name
54
54
  end
55
55
 
56
- def <=>(other) #:nodoc:
56
+ def <=>(other) # @private :nodoc:
57
57
  name <=> other.name
58
58
  end
59
59
 
60
- def inspect #:nodoc:
60
+ def inspect # @private :nodoc:
61
61
  "#<#{self.class.name}:0x%.14x @column=#{name.inspect} @type=#{type.inspect}>" % (object_id << 1)
62
62
  end
63
63
 
64
- def to_s #:nodoc:
64
+ def to_s # @private :nodoc:
65
65
  name
66
66
  end
67
67
 
@@ -1,110 +1,150 @@
1
1
  require "rails_erd/domain"
2
- require "graphviz"
3
- require "erb"
4
2
 
5
3
  module RailsERD
6
- # Create Graphviz-based diagrams based on the domain model. For easy
7
- # command line graph generation, you can use rake:
4
+ # This class is an abstract class that will process a domain model and
5
+ # allows easy creation of diagrams. To implement a new diagram type, derive
6
+ # from this class and override +process_entity+, +process_relationship+,
7
+ # and (optionally) +save+.
8
8
  #
9
- # % rake erd
9
+ # As an example, a diagram class that generates code that can be used with
10
+ # yUML (http://yuml.me) can be as simple as:
10
11
  #
11
- # Please see the README.rdoc file for more details on how to use Rails ERD
12
- # from the command line.
12
+ # require "rails_erd/diagram"
13
+ #
14
+ # class YumlDiagram < RailsERD::Diagram
15
+ # def process_relationship(rel)
16
+ # return if rel.indirect?
17
+ #
18
+ # arrow = case
19
+ # when rel.cardinality.one_to_one? then "1-1>"
20
+ # when rel.cardinality.one_to_many? then "1-*>"
21
+ # when rel.cardinality.many_to_many? then "*-*>"
22
+ # end
23
+ #
24
+ # instructions << "[#{rel.source}] #{arrow} [#{rel.destination}]"
25
+ # end
26
+ #
27
+ # def save
28
+ # instructions * "\n"
29
+ # end
30
+ #
31
+ # def instructions
32
+ # @instructions ||= []
33
+ # end
34
+ # end
35
+ #
36
+ # Then, to generate the diagram (example based on the domain model of Gemcutter):
37
+ #
38
+ # YumlDiagram.create
39
+ # #=> "[Rubygem] 1-*> [Ownership]
40
+ # # [Rubygem] 1-*> [Subscription]
41
+ # # [Rubygem] 1-*> [Version]
42
+ # # [Rubygem] 1-1> [Linkset]
43
+ # # [Rubygem] 1-*> [Dependency]
44
+ # # [Version] 1-*> [Dependency]
45
+ # # [User] 1-*> [Ownership]
46
+ # # [User] 1-*> [Subscription]
47
+ # # [User] 1-*> [WebHook]"
48
+ #
49
+ # For another example implementation, see Diagram::Graphviz, which is the
50
+ # default (and currently only) diagram type that is used by Rails ERD.
13
51
  class Diagram
14
- NODE_LABEL_TEMPLATE = File.read(File.expand_path("templates/node.erb", File.dirname(__FILE__))) #:nodoc:
15
- NODE_WIDTH = 130 #:nodoc:
16
-
17
52
  class << self
18
- # Generate a new domain model based on all <tt>ActiveRecord::Base</tt>
19
- # subclasses, and create a new diagram. Use the given options for both
53
+ # Generates a new domain model based on all <tt>ActiveRecord::Base</tt>
54
+ # subclasses, and creates a new diagram. Use the given options for both
20
55
  # the domain generation and the diagram generation.
21
- def generate(options = {})
22
- new(Domain.generate(options), options).output
56
+ def create(options = {})
57
+ new(Domain.generate(options), options).create
23
58
  end
24
59
  end
60
+
61
+ # The options that are used to create this diagram.
62
+ attr_reader :options
25
63
 
26
- attr_reader :options #:nodoc:
64
+ # The domain that this diagram represents.
65
+ attr_reader :domain
27
66
 
28
67
  # Create a new diagram based on the given domain.
29
68
  def initialize(domain, options = {})
30
69
  @domain, @options = domain, RailsERD.options.merge(options)
31
70
  end
32
71
 
33
- # Save the diagram.
34
- def output
35
- graph.output(options.file_type.to_sym => file_name)
36
- self
37
- end
38
-
39
- # Returns the file name that will be used when saving the diagram.
40
- def file_name
41
- "ERD.#{options.file_type}"
72
+ # Generates and saves the diagram, returning the result of +save+.
73
+ def create
74
+ generate
75
+ save
42
76
  end
43
77
 
44
- private
45
-
46
- def graph
47
- @graph ||= GraphViz.new(@domain.name, :type => :digraph) do |graph|
48
- graph[:rankdir] = horizontal? ? :LR : :TB
49
- graph[:ranksep] = 0.5
50
- graph[:nodesep] = 0.35
51
- graph[:margin] = "0.4,0.4"
52
- graph[:concentrate] = true
53
- graph[:label] = "#{@domain.name} domain model\\n\\n"
54
- graph[:labelloc] = :t
55
- graph[:fontsize] = 13
56
- graph[:fontname] = "Arial Bold"
57
- graph[:remincross] = true
58
- graph[:outputorder] = :edgesfirst
59
-
60
- graph.node[:shape] = "Mrecord"
61
- graph.node[:fontsize] = 10
62
- graph.node[:fontname] = "Arial"
63
- graph.node[:margin] = "0.07,0.05"
78
+ # Generates the diagram, but does not save the output. It is called
79
+ # internally by Diagram#create.
80
+ def generate
81
+ filtered_entities.each do |entity|
82
+ process_entity entity, filtered_attributes(entity)
83
+ end
64
84
 
65
- graph.edge[:fontname] = "Arial"
66
- graph.edge[:fontsize] = 8
67
- graph.edge[:dir] = :both
68
- graph.edge[:arrowsize] = 0.8
69
-
70
- nodes = {}
85
+ filtered_relationships.each do |relationship|
86
+ process_relationship relationship
87
+ end
88
+ end
71
89
 
72
- @domain.entities.each do |entity|
73
- if options.exclude_unconnected && !entity.connected?
74
- warn "Skipping unconnected model #{entity.name} (use exclude_unconnected=false to include)"
75
- next
76
- end
77
-
78
- attributes = entity.attributes.reject { |attribute|
79
- options.exclude_primary_keys && attribute.primary_key? or
80
- options.exclude_foreign_keys && attribute.foreign_key? or
81
- options.exclude_timestamps && attribute.timestamp?
82
- }
83
-
84
- nodes[entity] = graph.add_node entity.name, :label => "<" + ERB.new(NODE_LABEL_TEMPLATE, nil, "<>").result(binding) + ">"
85
- end
86
-
87
- raise "No (connected) entities found; create your models first!" if nodes.empty?
90
+ # Saves the diagram. Can be overridden in subclasses to write to an output
91
+ # file. It is called internally by Diagram#create.
92
+ def save
93
+ end
88
94
 
89
- @domain.relationships.each do |relationship|
90
- options = {}
91
- options[:arrowhead] = relationship.cardinality.one_to_one? ? :dot : :normal
92
- options[:arrowtail] = relationship.cardinality.many_to_many? ? :normal : :dot
93
- options[:weight] = relationship.strength
94
- options.merge! :style => :dashed, :constraint => false if relationship.indirect?
95
+ protected
95
96
 
96
- graph.add_edge nodes[relationship.source], nodes[relationship.destination], options
97
- end
98
- end
97
+ # Process a given entity and its attributes. This method should be implemented
98
+ # by subclasses. It is intended to add a representation of the entity to
99
+ # the diagram. This method will be called once for each entity that should
100
+ # be displayed, typically in alphabetic order.
101
+ def process_entity(entity, attributes)
102
+ end
103
+
104
+ # Process a given relationship. This method should be implemented by
105
+ # subclasses. It should add a representation of the relationship to
106
+ # the diagram. This method will be called once for eacn relationship
107
+ # that should be displayed.
108
+ def process_relationship(relationship)
99
109
  end
100
110
 
111
+ # Returns +true+ if the layout or hierarchy of the diagram should be
112
+ # horizontally oriented.
101
113
  def horizontal?
102
114
  options.orientation == :horizontal
103
115
  end
104
116
 
117
+ # Returns +true+ if the layout or hierarchy of the diagram should be
118
+ # vertically oriented.
105
119
  def vertical?
106
120
  !horizontal?
107
121
  end
122
+
123
+ private
124
+
125
+ def filtered_entities
126
+ @domain.entities.collect do |entity|
127
+ if options.exclude_unconnected && !entity.connected?
128
+ warn "Skipping unconnected model #{entity.name} (use exclude_unconnected=false to include)"
129
+ else
130
+ entity
131
+ end
132
+ end.compact.tap do |entities|
133
+ raise "No (connected) entities found; create your models first!" if entities.empty?
134
+ end
135
+ end
136
+
137
+ def filtered_relationships
138
+ @domain.relationships
139
+ end
140
+
141
+ def filtered_attributes(entity)
142
+ entity.attributes.reject { |attribute|
143
+ options.exclude_primary_keys && attribute.primary_key? or
144
+ options.exclude_foreign_keys && attribute.foreign_key? or
145
+ options.exclude_timestamps && attribute.timestamp?
146
+ }
147
+ end
108
148
 
109
149
  def warn(message)
110
150
  puts "Warning: #{message}" unless options.suppress_warnings
@@ -0,0 +1,120 @@
1
+ require "rails_erd/diagram"
2
+ require "graphviz"
3
+ require "erb"
4
+
5
+ # Fix bad RegEx test in Ruby-Graphviz.
6
+ GraphViz::Types::LblString.class_eval do
7
+ def output
8
+ if /^<.*>$/m =~ @data
9
+ @data
10
+ else
11
+ @data.to_s.inspect.gsub("\\\\", "\\")
12
+ end
13
+ end
14
+ alias_method :to_gv, :output
15
+ alias_method :to_s, :output
16
+ end
17
+
18
+ module RailsERD
19
+ class Diagram
20
+ # Create Graphviz-based diagrams based on the domain model. For easy
21
+ # command line graph generation, you can use rake:
22
+ #
23
+ # % rake erd
24
+ #
25
+ # Please see the README.rdoc file for more details on how to use Rails ERD
26
+ # from the command line.
27
+ class Graphviz < Diagram
28
+ NODE_LABEL_TEMPLATE = ERB.new(File.read(File.expand_path("templates/node.erb", File.dirname(__FILE__))), nil, "<>") # @private :nodoc:
29
+
30
+ NODE_WIDTH = 130 # @private :nodoc:
31
+
32
+ # Default graph attributes.
33
+ GRAPH_ATTRIBUTES = {
34
+ :rankdir => :LR,
35
+ :ranksep => 0.5,
36
+ :nodesep => 0.35,
37
+ :margin => "0.4,0.4",
38
+ :concentrate => true,
39
+ :labelloc => :t,
40
+ :fontsize => 13,
41
+ :fontname => "Arial Bold",
42
+ :remincross => true,
43
+ :outputorder => :edgesfirst }
44
+
45
+ # Default node attributes.
46
+ NODE_ATTRIBUTES = {
47
+ :shape => "Mrecord",
48
+ :fontsize => 10,
49
+ :fontname => "Arial",
50
+ :margin => "0.07,0.05",
51
+ :penwidth => 0.8 }
52
+
53
+ # Default edge attributes.
54
+ EDGE_ATTRIBUTES = {
55
+ :fontname => "Arial",
56
+ :fontsize => 8,
57
+ :dir => :both,
58
+ :arrowsize => 0.7,
59
+ :penwidth => 0.8 }
60
+
61
+ def graph
62
+ @graph ||= GraphViz.digraph(@domain.name) do |graph|
63
+ # Set all default attributes.
64
+ GRAPH_ATTRIBUTES.each { |attribute, value| graph[attribute] = value }
65
+ NODE_ATTRIBUTES.each { |attribute, value| graph.node[attribute] = value }
66
+ EDGE_ATTRIBUTES.each { |attribute, value| graph.edge[attribute] = value }
67
+
68
+ # Switch rank direction if we're told to create a vertically
69
+ # oriented graph.
70
+ graph[:rankdir] = :TB if vertical?
71
+
72
+ # Title of the graph itself.
73
+ graph[:label] = "#{@domain.name} domain model\\n\\n"
74
+ end
75
+ end
76
+
77
+ # Save the diagram and return the file name that was written to.
78
+ def save
79
+ graph.output(options.file_type.to_sym => file_name)
80
+ file_name
81
+ end
82
+
83
+ protected
84
+
85
+ def process_entity(entity, attributes)
86
+ graph.add_node entity.name, entity_options(entity, attributes)
87
+ end
88
+
89
+ def process_relationship(relationship)
90
+ graph.add_edge graph.get_node(relationship.source.name), graph.get_node(relationship.destination.name),
91
+ relationship_options(relationship)
92
+ end
93
+
94
+ private
95
+
96
+ # Returns the file name that will be used when saving the diagram.
97
+ def file_name
98
+ "ERD.#{options.file_type}"
99
+ end
100
+
101
+ # Returns an options hash based on the given entity and its attributes.
102
+ def entity_options(entity, attributes)
103
+ { :label => "<#{NODE_LABEL_TEMPLATE.result(binding)}>" }
104
+ end
105
+
106
+ # Returns an options hash
107
+ def relationship_options(relationship)
108
+ {}.tap do |options|
109
+ options[:arrowhead] = relationship.cardinality.one_to_one? ? :dot : :normal
110
+ options[:arrowtail] = relationship.cardinality.many_to_many? ? :normal : :dot
111
+ options[:weight] = relationship.strength
112
+ if relationship.indirect?
113
+ options[:style] = :dotted
114
+ options[:constraint] = false
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,13 +1,17 @@
1
1
  <% if vertical? %>{<% end %>
2
2
  <table border="0" align="center" cellspacing="0.5" cellpadding="0" width="<%= NODE_WIDTH + 4 %>">
3
3
  <tr><td align="center" valign="bottom" width="<%= NODE_WIDTH %>"><font face="Arial Bold" point-size="11"><%= entity.name %></font></td></tr>
4
- </table>|<% if attributes.any? %>
5
- <table border="0" align="left" cellspacing="2" cellpadding="0" width="<%= NODE_WIDTH + 4 %>">
4
+ </table>
5
+ |
6
+ <table border="0" align="left" cellspacing="2" cellpadding="0" width="<%= NODE_WIDTH + 4 %>">
7
+ <% if attributes.any? %>
6
8
  <% attributes.each do |attribute| %>
7
9
  <tr>
8
10
  <td align="left" width="<%= NODE_WIDTH %>" port="<%= attribute %>"><%= attribute %> <font face="Arial Italic" color="grey60"><%= attribute.type_description %></font></td>
9
11
  </tr>
10
12
  <% end %>
11
- </table>
12
- <% end %>
13
+ <% else %>
14
+ <tr><td height="6"></td></tr>
15
+ <% end %>
16
+ </table>
13
17
  <% if vertical? %>}<% end %>
@@ -21,7 +21,8 @@ module RailsERD
21
21
  end
22
22
  end
23
23
 
24
- attr_reader :options #:nodoc:
24
+ # The options that are used to generate this domain model.
25
+ attr_reader :options
25
26
 
26
27
  # Create a new domain model object based on the given array of models.
27
28
  # The given models are assumed to be subclasses of <tt>ActiveRecord::Base</tt>.
@@ -46,17 +47,18 @@ module RailsERD
46
47
  end
47
48
 
48
49
  # Returns a specific entity object for the given Active Record model.
49
- def entity_for(model) #:nodoc:
50
+ def entity_for(model) # @private :nodoc:
50
51
  entity_mapping[model] or raise "model #{model} exists, but is not included in the domain"
51
52
  end
52
53
 
53
54
  # Returns an array of relationships for the given Active Record model.
54
- def relationships_for(model) #:nodoc:
55
+ def relationships_for(model) # @private :nodoc:
55
56
  relationships_mapping[model] or []
56
57
  end
57
58
 
58
- def inspect #:nodoc:
59
- "#<#{self.class} {#{relationships.map { |rel| "#{rel.from} => #{rel.to}" } * ", "}}>"
59
+ def inspect # @private :nodoc:
60
+ "#<#{self.class}:0x%.14x {%s}>" %
61
+ [object_id << 1, relationships.map { |rel| "#{rel.source} => #{rel.destination}" } * ", "]
60
62
  end
61
63
 
62
64
  private
@@ -8,7 +8,7 @@ module RailsERD
8
8
  # The Active Record model that this entity corresponds to.
9
9
  attr_reader :model
10
10
 
11
- def initialize(domain, model) #:nodoc:
11
+ def initialize(domain, model) # @private :nodoc:
12
12
  @domain, @model = domain, model
13
13
  end
14
14
 
@@ -35,15 +35,15 @@ module RailsERD
35
35
  model.name
36
36
  end
37
37
 
38
- def inspect #:nodoc:
38
+ def inspect # @private :nodoc:
39
39
  "#<#{self.class}:0x%.14x @model=#{name}>" % (object_id << 1)
40
40
  end
41
41
 
42
- def to_s #:nodoc:
42
+ def to_s # @private :nodoc:
43
43
  name
44
44
  end
45
45
 
46
- def <=>(other) #:nodoc:
46
+ def <=>(other) # @private :nodoc:
47
47
  self.name <=> other.name
48
48
  end
49
49
  end
@@ -1,5 +1,8 @@
1
1
  module RailsERD
2
- class Railtie < Rails::Railtie #:nodoc:
2
+ # Rails ERD integrates with Rails 3. If you add it to your +Gemfile+, you
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.
5
+ class Railtie < Rails::Railtie
3
6
  rake_tasks do
4
7
  load "rails_erd/tasks.rake"
5
8
  end
@@ -5,7 +5,7 @@ module RailsERD
5
5
  # key are grouped together.
6
6
  class Relationship
7
7
  class << self
8
- def from_associations(domain, associations) #:nodoc:
8
+ def from_associations(domain, associations) # @private :nodoc:
9
9
  assoc_groups = associations.group_by { |assoc| association_identity(assoc) }
10
10
  assoc_groups.collect { |_, assoc_group| Relationship.new(domain, assoc_group.to_a) }
11
11
  end
@@ -29,7 +29,7 @@ module RailsERD
29
29
  # a +belongs_to+ association with the other model.
30
30
  attr_reader :destination
31
31
 
32
- def initialize(domain, associations) #:nodoc:
32
+ def initialize(domain, associations) # @private :nodoc:
33
33
  @domain = domain
34
34
  @reverse_associations, @forward_associations = *associations.partition(&:belongs_to?)
35
35
 
@@ -56,7 +56,7 @@ module RailsERD
56
56
  # Rails with <tt>has_many :through</tt> or <tt>has_one :through</tt>
57
57
  # association macros.
58
58
  def indirect?
59
- @forward_associations.all?(&:through_reflection)
59
+ !@forward_associations.empty? and @forward_associations.all?(&:through_reflection)
60
60
  end
61
61
 
62
62
  # Indicates whether or not the relationship is defined by two inverse
@@ -77,11 +77,11 @@ module RailsERD
77
77
  associations.size
78
78
  end
79
79
 
80
- def inspect #:nodoc:
80
+ def inspect # @private :nodoc:
81
81
  "#<#{self.class}:0x%.14x @source=#{source} @destination=#{destination}>" % (object_id << 1)
82
82
  end
83
83
 
84
- def <=>(other) #:nodoc:
84
+ def <=>(other) # @private :nodoc:
85
85
  (source.name <=> other.source.name).nonzero? or (destination.name <=> other.destination.name)
86
86
  end
87
87
  end
@@ -1,14 +1,14 @@
1
1
  module RailsERD
2
2
  class Relationship
3
3
  class Cardinality
4
- CARDINALITY_NAMES = %w{one_to_one one_to_many many_to_many} #:nodoc:
5
- ORDER = {} #:nodoc:
4
+ CARDINALITY_NAMES = %w{one_to_one one_to_many many_to_many} # @private :nodoc:
5
+ ORDER = {} # @private :nodoc:
6
6
 
7
7
  class << self
8
- # Returns the cardinality as symbol.
8
+ # Returns the cardinality as a symbol.
9
9
  attr_reader :type
10
-
11
- def from_macro(macro) #:nodoc:
10
+
11
+ def from_macro(macro) # @private :nodoc:
12
12
  case macro
13
13
  when :has_and_belongs_to_many then ManyToMany
14
14
  when :has_many then OneToMany
@@ -16,7 +16,7 @@ module RailsERD
16
16
  end
17
17
  end
18
18
 
19
- def <=>(other) #:nodoc:
19
+ def <=>(other) # @private :nodoc:
20
20
  ORDER[self] <=> ORDER[other]
21
21
  end
22
22
 
@@ -28,7 +28,7 @@ module RailsERD
28
28
  end
29
29
 
30
30
  CARDINALITY_NAMES.each_with_index do |cardinality, i|
31
- klass = Cardinality.const_set cardinality.camelize.to_sym, Class.new(Cardinality) { @@type = cardinality }
31
+ klass = Cardinality.const_set cardinality.camelize.to_sym, Class.new(Cardinality) { @type = cardinality }
32
32
  ORDER[klass] = i
33
33
  end
34
34
  end
@@ -14,7 +14,7 @@ namespace :erd do
14
14
  end
15
15
 
16
16
  task :load_models do
17
- say "Loading ActiveRecord models..."
17
+ say "Loading Active Record models..."
18
18
 
19
19
  Rake::Task[:environment].invoke
20
20
  Rails.application.config.paths.app.models.paths.each do |model_path|
@@ -25,12 +25,12 @@ namespace :erd do
25
25
  end
26
26
 
27
27
  task :generate => [:options, :load_models] do
28
- say "Generating ERD diagram..."
28
+ say "Generating Entity-Relationship Diagram..."
29
29
 
30
- require "rails_erd/diagram"
31
- diagram = RailsERD::Diagram.generate
30
+ require "rails_erd/diagram/graphviz"
31
+ file = RailsERD::Diagram::Graphviz.create
32
32
 
33
- say "Done! Saved diagram to #{diagram.file_name}."
33
+ say "Done! Saved diagram to #{file}."
34
34
  end
35
35
  end
36
36
 
data/rails-erd.gemspec ADDED
@@ -0,0 +1,89 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rails-erd}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Rolf Timmermans"]
12
+ s.date = %q{2010-09-21}
13
+ s.description = %q{Automatically generate an entity-relationship diagram (ERD) for your Rails models.}
14
+ s.email = %q{r.timmermans@voormedia.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "CHANGES.rdoc",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/rails-erd.rb",
27
+ "lib/rails_erd.rb",
28
+ "lib/rails_erd/attribute.rb",
29
+ "lib/rails_erd/diagram.rb",
30
+ "lib/rails_erd/diagram/graphviz.rb",
31
+ "lib/rails_erd/diagram/templates/node.erb",
32
+ "lib/rails_erd/domain.rb",
33
+ "lib/rails_erd/entity.rb",
34
+ "lib/rails_erd/railtie.rb",
35
+ "lib/rails_erd/relationship.rb",
36
+ "lib/rails_erd/relationship/cardinality.rb",
37
+ "lib/rails_erd/tasks.rake",
38
+ "rails-erd.gemspec",
39
+ "test/test_helper.rb",
40
+ "test/unit/attribute_test.rb",
41
+ "test/unit/cardinality_test.rb",
42
+ "test/unit/diagram_test.rb",
43
+ "test/unit/domain_test.rb",
44
+ "test/unit/entity_test.rb",
45
+ "test/unit/graphviz_test.rb",
46
+ "test/unit/rake_task_test.rb",
47
+ "test/unit/relationship_test.rb"
48
+ ]
49
+ s.homepage = %q{http://rails-erd.rubyforge.org/}
50
+ s.rdoc_options = ["--charset=UTF-8"]
51
+ s.require_paths = ["lib"]
52
+ s.rubyforge_project = %q{rails-erd}
53
+ s.rubygems_version = %q{1.3.7}
54
+ s.summary = %q{Entity-relationship diagram for your Rails models.}
55
+ s.test_files = [
56
+ "test/test_helper.rb",
57
+ "test/unit/attribute_test.rb",
58
+ "test/unit/cardinality_test.rb",
59
+ "test/unit/diagram_test.rb",
60
+ "test/unit/domain_test.rb",
61
+ "test/unit/entity_test.rb",
62
+ "test/unit/graphviz_test.rb",
63
+ "test/unit/rake_task_test.rb",
64
+ "test/unit/relationship_test.rb"
65
+ ]
66
+
67
+ if s.respond_to? :specification_version then
68
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
69
+ s.specification_version = 3
70
+
71
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
72
+ s.add_runtime_dependency(%q<activerecord>, ["~> 3.0.0"])
73
+ s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.0"])
74
+ s.add_runtime_dependency(%q<ruby-graphviz>, ["~> 0.9.17"])
75
+ s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
76
+ else
77
+ s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
78
+ s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
79
+ s.add_dependency(%q<ruby-graphviz>, ["~> 0.9.17"])
80
+ s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
81
+ end
82
+ else
83
+ s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
84
+ s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
85
+ s.add_dependency(%q<ruby-graphviz>, ["~> 0.9.17"])
86
+ s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
87
+ end
88
+ end
89
+
data/test/test_helper.rb CHANGED
@@ -4,8 +4,8 @@ require "active_support/test_case"
4
4
 
5
5
  require "rails_erd/domain"
6
6
 
7
- require "rails"
8
7
  require "active_record"
8
+ require "sqlite3"
9
9
 
10
10
  ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => ":memory:"
11
11
 
@@ -57,6 +57,13 @@ class ActiveSupport::TestCase
57
57
  $stdout = stdout
58
58
  end
59
59
 
60
+ def create_simple_domain
61
+ create_model "Foo", :bar => :references do
62
+ belongs_to :bar
63
+ end
64
+ create_model "Bar"
65
+ end
66
+
60
67
  private
61
68
 
62
69
  def reset_domain
@@ -1,8 +1,25 @@
1
1
  require File.expand_path("../test_helper", File.dirname(__FILE__))
2
2
 
3
3
  class CardinalityTest < ActiveSupport::TestCase
4
+ # Cardinality order ========================================================
4
5
  test "cardinalities should be sorted in order of maniness" do
5
6
  assert_equal [Relationship::Cardinality::OneToOne, Relationship::Cardinality::OneToMany, Relationship::Cardinality::ManyToMany],
6
7
  [Relationship::Cardinality::OneToMany, Relationship::Cardinality::ManyToMany, Relationship::Cardinality::OneToOne].sort
7
8
  end
9
+
10
+ # Cardinality properties ===================================================
11
+ test "one_to_one should return true for one to one cardinalities" do
12
+ assert_equal [true, false, false], [Relationship::Cardinality::OneToOne,
13
+ Relationship::Cardinality::OneToMany, Relationship::Cardinality::ManyToMany].map(&:one_to_one?)
14
+ end
15
+
16
+ test "one_to_many should return true for one to many cardinalities" do
17
+ assert_equal [false, true, false], [Relationship::Cardinality::OneToOne,
18
+ Relationship::Cardinality::OneToMany, Relationship::Cardinality::ManyToMany].map(&:one_to_many?)
19
+ end
20
+
21
+ test "many_to_many should return true for many to many cardinalities" do
22
+ assert_equal [false, false, true], [Relationship::Cardinality::OneToOne,
23
+ Relationship::Cardinality::OneToMany, Relationship::Cardinality::ManyToMany].map(&:many_to_many?)
24
+ end
8
25
  end
@@ -1,34 +1,57 @@
1
1
  require File.expand_path("../test_helper", File.dirname(__FILE__))
2
2
 
3
- require "rails_erd/diagram"
4
-
5
3
  class DiagramTest < ActiveSupport::TestCase
4
+ def setup
5
+ load "rails_erd/diagram.rb"
6
+ end
7
+
6
8
  def teardown
7
- FileUtils.rm "ERD.dot" rescue nil
9
+ RailsERD.send :remove_const, :Diagram
8
10
  end
9
11
 
10
- # Diagram generation =======================================================
11
- test "generate should create output based on domain model" do
12
- create_model "Foo", :bar => :references do
13
- belongs_to :bar
12
+ # Diagram ==================================================================
13
+ test "create class method should return result of save" do
14
+ create_simple_domain
15
+ subclass = Class.new(Diagram) do
16
+ def save
17
+ "foobar"
18
+ end
14
19
  end
15
- create_model "Bar"
16
- RailsERD::Diagram.generate(:file_type => :dot)
17
- assert File.exists?("ERD.dot")
20
+ assert_equal "foobar", subclass.create
21
+ end
22
+
23
+ test "create should return result of save" do
24
+ create_simple_domain
25
+ diagram = Class.new(Diagram) do
26
+ def save
27
+ "foobar"
28
+ end
29
+ end.new(Domain.generate)
30
+ assert_equal "foobar", diagram.create
31
+ end
32
+
33
+ test "domain sould return given domain" do
34
+ domain = Object.new
35
+ assert_same domain, Class.new(Diagram).new(domain).domain
18
36
  end
19
37
 
20
- test "generate should not create output if there are no connected models" do
21
- RailsERD::Diagram.generate(:file_type => :dot) rescue nil
22
- assert !File.exists?("ERD.dot")
38
+ # Diagram abstractness =====================================================
39
+ test "create should succeed silently if called on abstract class" do
40
+ create_simple_domain
41
+ assert_nothing_raised do
42
+ Diagram.create
43
+ end
23
44
  end
24
45
 
25
- test "generate should abort and complain if there are no connected models" do
26
- message = nil
27
- begin
28
- RailsERD::Diagram.generate(:file_type => :dot)
29
- rescue => e
30
- message = e.message
46
+ test "create should succeed if called on class that implements process_entity and process_relationship" do
47
+ create_simple_domain
48
+ assert_nothing_raised do
49
+ Class.new(Diagram) do
50
+ def process_entity(*args)
51
+ end
52
+ def process_relationship(*args)
53
+ end
54
+ end.create
31
55
  end
32
- assert_match /No \(connected\) entities found/, message
33
56
  end
34
57
  end
@@ -7,15 +7,30 @@ class DomainTest < ActiveSupport::TestCase
7
7
  end
8
8
 
9
9
  test "name should return rails application name" do
10
- Object::Quux = Module.new
11
- Object::Quux::Application = Class.new Rails::Application
12
- assert_equal "Quux", Domain.generate.name
10
+ begin
11
+ Object::Quux = Module.new
12
+ Object::Quux::Application = Class.new
13
+ Object::Rails = Struct.new(:application).new(Object::Quux::Application.new)
14
+ assert_equal "Quux", Domain.generate.name
15
+ ensure
16
+ Object::Quux.send :remove_const, :Application
17
+ Object.send :remove_const, :Quux
18
+ Object.send :remove_const, :Rails
19
+ end
13
20
  end
14
21
 
15
22
  test "name should return nil outside rails" do
16
23
  assert_nil Domain.generate.name
17
24
  end
18
25
 
26
+ test "inspect should display relationships" do
27
+ create_model "Foo", :bar => :references do
28
+ belongs_to :bar
29
+ end
30
+ create_model "Bar"
31
+ assert_match %r{#<RailsERD::Domain:.* {Bar => Foo}>}, Domain.generate.inspect
32
+ end
33
+
19
34
  # Entity processing ========================================================
20
35
  test "entity_for should return associated entity for given model" do
21
36
  create_model "Foo"
@@ -0,0 +1,140 @@
1
+ require File.expand_path("../test_helper", File.dirname(__FILE__))
2
+
3
+ class GraphvizTest < ActiveSupport::TestCase
4
+ def setup
5
+ RailsERD.options.file_type = :dot
6
+ load "rails_erd/diagram/graphviz.rb"
7
+ end
8
+
9
+ def teardown
10
+ FileUtils.rm "ERD.dot" rescue nil
11
+ RailsERD::Diagram.send :remove_const, :Graphviz
12
+ end
13
+
14
+ def diagram
15
+ @diagram ||= Diagram::Graphviz.new(Domain.generate).tap do |diagram|
16
+ diagram.generate
17
+ end
18
+ end
19
+
20
+ def find_dot_nodes(diagram)
21
+ [].tap do |nodes|
22
+ diagram.graph.each_node do |node|
23
+ nodes << node
24
+ end
25
+ end
26
+ end
27
+
28
+ def find_dot_edges(diagram)
29
+ [].tap do |edges|
30
+ diagram.graph.each_edge do |edge|
31
+ edges << [edge.node_one, edge.node_two]
32
+ end
33
+ end
34
+ end
35
+
36
+ # Diagram properties =======================================================
37
+ test "file name should depend on file type" do
38
+ create_simple_domain
39
+ begin
40
+ assert_equal "ERD.svg", Diagram::Graphviz.create(:file_type => :svg)
41
+ ensure
42
+ FileUtils.rm "ERD.svg" rescue nil
43
+ end
44
+ end
45
+
46
+ # Diagram generation =======================================================
47
+ test "create should create output based on domain model" do
48
+ create_model "Foo", :bar => :references, :column => :string do
49
+ belongs_to :bar
50
+ end
51
+ create_model "Bar", :column => :string
52
+ Diagram::Graphviz.create
53
+ assert File.exists?("ERD.dot")
54
+ end
55
+
56
+ test "create should create output based on domain without attributes" do
57
+ create_model "Foo", :bar => :references do
58
+ belongs_to :bar
59
+ end
60
+ create_model "Bar"
61
+ Diagram::Graphviz.create
62
+ assert File.exists?("ERD.dot")
63
+ end
64
+
65
+ test "create should create vertical output based on domain model" do
66
+ create_model "Foo", :bar => :references, :column => :string do
67
+ belongs_to :bar
68
+ end
69
+ create_model "Bar", :column => :string
70
+ Diagram::Graphviz.create(:orientation => :vertical)
71
+ assert File.exists?("ERD.dot")
72
+ end
73
+
74
+ test "create should create vertical output based on domain without attributes" do
75
+ create_model "Foo", :bar => :references do
76
+ belongs_to :bar
77
+ end
78
+ create_model "Bar"
79
+ Diagram::Graphviz.create(:orientation => :vertical)
80
+ assert File.exists?("ERD.dot")
81
+ end
82
+
83
+ test "create should not create output if there are no connected models" do
84
+ Diagram::Graphviz.create rescue nil
85
+ assert !File.exists?("ERD.dot")
86
+ end
87
+
88
+ test "create should abort and complain if there are no connected models" do
89
+ message = nil
90
+ begin
91
+ Diagram::Graphviz.create
92
+ rescue => e
93
+ message = e.message
94
+ end
95
+ assert_match /No \(connected\) entities found/, message
96
+ end
97
+
98
+ # Graphviz output ==========================================================
99
+ test "generate should create directed graph" do
100
+ create_simple_domain
101
+ assert_equal "digraph", diagram.graph.type
102
+ end
103
+
104
+ test "generate should create node for each entity" do
105
+ create_model "Foo", :bar => :references do
106
+ belongs_to :bar
107
+ end
108
+ create_model "Bar"
109
+ assert_equal ["Bar", "Foo"], find_dot_nodes(diagram).sort
110
+ end
111
+
112
+ test "generate should add label for entities" do
113
+ create_model "Foo", :bar => :references do
114
+ belongs_to :bar
115
+ end
116
+ create_model "Bar"
117
+ assert_match %r{<\w+.*?>Bar</\w+>},
118
+ diagram.graph.get_node(find_dot_nodes(diagram).first)[:label].to_gv
119
+ end
120
+
121
+ test "generate should add attributes to entity labels" do
122
+ create_model "Foo", :bar => :references do
123
+ belongs_to :bar
124
+ end
125
+ create_model "Bar", :column => :string
126
+ assert_match %r{<\w+.*?>column <\w+.*?>str</\w+.*?>},
127
+ diagram.graph.get_node(find_dot_nodes(diagram).first)[:label].to_gv
128
+ end
129
+
130
+
131
+ test "generate should create edge for each relationship" do
132
+ create_model "Foo", :bar => :references do
133
+ belongs_to :bar
134
+ end
135
+ create_model "Bar", :foo => :references do
136
+ belongs_to :foo
137
+ end
138
+ assert_equal [["Bar", "Foo"], ["Foo", "Bar"]], find_dot_edges(diagram).sort
139
+ end
140
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path("../test_helper", File.dirname(__FILE__))
2
+
3
+ class RakeTaskTest < ActiveSupport::TestCase
4
+ include ActiveSupport::Testing::Isolation
5
+
6
+ def setup
7
+ require "rake"
8
+ load "rails_erd/tasks.rake"
9
+
10
+ RailsERD.options.file_type = :dot
11
+ RailsERD.options.suppress_warnings = true
12
+ Rake.application.options.silent = true
13
+ end
14
+
15
+ def teardown
16
+ FileUtils.rm "ERD.dot" rescue nil
17
+ RailsERD::Diagram.send :remove_const, :Graphviz rescue nil
18
+ end
19
+
20
+ # Diagram generation =======================================================
21
+ test "generate task should create output based on domain model" do
22
+ create_simple_domain
23
+ Rake::Task["erd:generate"].execute
24
+ assert File.exists?("ERD.dot")
25
+ end
26
+
27
+ test "generate task should not create output if there are no connected models" do
28
+ Rake::Task["erd:generate"].execute rescue nil
29
+ assert !File.exists?("ERD.dot")
30
+ end
31
+ end
@@ -80,6 +80,15 @@ class RelationshipTest < ActiveSupport::TestCase
80
80
  assert_equal [false], domain.relationships.map(&:indirect?)
81
81
  end
82
82
 
83
+ test "indirect should return false for non mutual ordinary relationship" do
84
+ create_model "Foo", :bar => :references do
85
+ belongs_to :bar
86
+ end
87
+ create_model "Bar"
88
+ domain = Domain.generate
89
+ assert_equal [false], domain.relationships.map(&:indirect?)
90
+ end
91
+
83
92
  test "indirect should return true if relationship is a through association" do
84
93
  create_model "Foo", :baz => :references, :bar => :references do
85
94
  belongs_to :baz
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-erd
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Rolf Timmermans
@@ -15,18 +14,17 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-09-20 00:00:00 +02:00
17
+ date: 2010-09-21 00:00:00 +02:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
- name: activesupport
21
+ name: activerecord
23
22
  prerelease: false
24
23
  requirement: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
25
  requirements:
27
26
  - - ~>
28
27
  - !ruby/object:Gem::Version
29
- hash: 7
30
28
  segments:
31
29
  - 3
32
30
  - 0
@@ -35,21 +33,48 @@ dependencies:
35
33
  type: :runtime
36
34
  version_requirements: *id001
37
35
  - !ruby/object:Gem::Dependency
38
- name: ruby-graphviz
36
+ name: activesupport
39
37
  prerelease: false
40
38
  requirement: &id002 !ruby/object:Gem::Requirement
41
39
  none: false
42
40
  requirements:
43
41
  - - ~>
44
42
  - !ruby/object:Gem::Version
45
- hash: 25
43
+ segments:
44
+ - 3
45
+ - 0
46
+ - 0
47
+ version: 3.0.0
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: ruby-graphviz
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
46
58
  segments:
47
59
  - 0
48
60
  - 9
49
61
  - 17
50
62
  version: 0.9.17
51
63
  type: :runtime
52
- version_requirements: *id002
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: sqlite3-ruby
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ type: :development
77
+ version_requirements: *id004
53
78
  description: Automatically generate an entity-relationship diagram (ERD) for your Rails models.
54
79
  email: r.timmermans@voormedia.com
55
80
  executables: []
@@ -70,19 +95,23 @@ files:
70
95
  - lib/rails_erd.rb
71
96
  - lib/rails_erd/attribute.rb
72
97
  - lib/rails_erd/diagram.rb
98
+ - lib/rails_erd/diagram/graphviz.rb
99
+ - lib/rails_erd/diagram/templates/node.erb
73
100
  - lib/rails_erd/domain.rb
74
101
  - lib/rails_erd/entity.rb
75
102
  - lib/rails_erd/railtie.rb
76
103
  - lib/rails_erd/relationship.rb
77
104
  - lib/rails_erd/relationship/cardinality.rb
78
105
  - lib/rails_erd/tasks.rake
79
- - lib/rails_erd/templates/node.erb
106
+ - rails-erd.gemspec
80
107
  - test/test_helper.rb
81
108
  - test/unit/attribute_test.rb
82
109
  - test/unit/cardinality_test.rb
83
110
  - test/unit/diagram_test.rb
84
111
  - test/unit/domain_test.rb
85
112
  - test/unit/entity_test.rb
113
+ - test/unit/graphviz_test.rb
114
+ - test/unit/rake_task_test.rb
86
115
  - test/unit/relationship_test.rb
87
116
  has_rdoc: true
88
117
  homepage: http://rails-erd.rubyforge.org/
@@ -98,7 +127,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
127
  requirements:
99
128
  - - ">="
100
129
  - !ruby/object:Gem::Version
101
- hash: 3
102
130
  segments:
103
131
  - 0
104
132
  version: "0"
@@ -107,7 +135,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
135
  requirements:
108
136
  - - ">="
109
137
  - !ruby/object:Gem::Version
110
- hash: 3
111
138
  segments:
112
139
  - 0
113
140
  version: "0"
@@ -125,4 +152,6 @@ test_files:
125
152
  - test/unit/diagram_test.rb
126
153
  - test/unit/domain_test.rb
127
154
  - test/unit/entity_test.rb
155
+ - test/unit/graphviz_test.rb
156
+ - test/unit/rake_task_test.rb
128
157
  - test/unit/relationship_test.rb