rails-erd 0.4.5 → 1.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.
data/CHANGES.rdoc CHANGED
@@ -1,3 +1,21 @@
1
+ === 1.0.0:
2
+
3
+ * The internal API is now stable and will be backwards compatible until
4
+ the next major version.
5
+ * Added experimental command line interface (erd). The CLI still requires a
6
+ Rails application to be present, but it may one day support other kinds of
7
+ applications.
8
+ * Crow's foot notation (also known as the Information Engineering notation)
9
+ can be used by adding 'notation=crowsfoot' to the 'rake erd' command
10
+ (contributed by Jeremy Holland).
11
+ * Filter models by using the only or exclude options (only=ModelOne,ModelTwo
12
+ or exclude=ModelThree,ModelFour) from the command line (contributed by
13
+ Milovan Zogovic).
14
+ * Process column types that are unsupported by Rails (contributed by Erik
15
+ Gustavson).
16
+ * Ignore custom limit/scale attributes that cannot be converted to an integer
17
+ (reported by Adam St. John).
18
+
1
19
  === 0.4.5:
2
20
 
3
21
  * Display more helpful error message when the application models could not be
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2011 Voormedia B.V.
1
+ Copyright (c) 2010-2012 Voormedia B.V.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -31,11 +31,11 @@ Getting started
31
31
  See the [installation instructions](http://rails-erd.rubyforge.org/install.html)
32
32
  for a complete description of how to install Rails ERD. Here's a summary:
33
33
 
34
- * Install Graphviz 2.22+ with Pango and Cairo support ([how?](http://rails-erd.rubyforge.org/install.html))
34
+ * Install Graphviz 2.22+ ([how?](http://rails-erd.rubyforge.org/install.html))
35
35
 
36
36
  * Add <tt>gem "rails-erd"</tt> to your application's Gemfile
37
37
 
38
- * Run <tt>rake erd</tt>
38
+ * Run <tt>bundle exec erd</tt>
39
39
 
40
40
 
41
41
  Learn more
@@ -51,7 +51,7 @@ About Rails ERD
51
51
 
52
52
  Rails ERD was created by Rolf Timmermans (r.timmermans *at* voormedia.com)
53
53
 
54
- Copyright 2010-2011 Voormedia - [www.voormedia.com](http://www.voormedia.com/)
54
+ Copyright 2010-2012 Voormedia - [www.voormedia.com](http://www.voormedia.com/)
55
55
 
56
56
 
57
57
  License
data/Rakefile CHANGED
@@ -1,54 +1,65 @@
1
- # encoding: utf-8
2
- require "jeweler"
1
+ require "bundler"
3
2
  require "rake/testtask"
4
3
 
5
- Jeweler::Tasks.new do |spec|
6
- spec.name = "rails-erd"
7
- spec.rubyforge_project = "rails-erd"
8
- spec.summary = "Entity-relationship diagram for your Rails models."
9
- spec.description = "Automatically generate an entity-relationship diagram (ERD) for your Rails models."
10
-
11
- spec.authors = ["Rolf Timmermans"]
12
- spec.email = "r.timmermans@voormedia.com"
13
- spec.homepage = "http://rails-erd.rubyforge.org/"
14
-
15
- # Don't bundle examples or website in gem.
16
- excluded = Dir["{examples,site}/**/*"]
17
- spec.files -= excluded
18
- spec.test_files -= excluded
19
- end
20
-
21
- Jeweler::GemcutterTasks.new
22
-
23
- Jeweler::RubyforgeTasks.new do |rubyforge|
24
- rubyforge.doc_task = "rdoc"
25
- rubyforge.remote_doc_path = "doc"
26
- end
4
+ Bundler::GemHelper.install_tasks
27
5
 
28
6
  Rake::TestTask.new do |test|
29
- test.pattern = "test/unit/**/*_test.rb"
7
+ test.test_files = FileList["test/**/*_test.rb"]
30
8
  end
31
9
 
32
10
  task :default => :test
33
11
 
34
- begin
35
- require "hanna/rdoctask"
36
- Rake::RDocTask.new do |rdoc|
37
- rdoc.rdoc_files = %w{CHANGES.rdoc LICENSE} + Dir["lib/**/*.rb"]
38
- rdoc.title = "Rails ERD – API Documentation"
39
- rdoc.rdoc_dir = "rdoc"
40
- rdoc.main = "RailsERD"
41
- end
42
- rescue LoadError
43
- end
44
-
45
- desc "Generate diagrams for bundled examples"
46
- task :examples do
47
- require File.expand_path("examples/generate", File.dirname(__FILE__))
48
- end
49
-
50
- namespace :examples do
51
- task :sfdp do
52
- require File.expand_path("examples/sfdp", File.dirname(__FILE__))
53
- end
54
- end
12
+ # # encoding: utf-8
13
+ # require "jeweler"
14
+ # require "rake/testtask"
15
+ #
16
+ # Jeweler::Tasks.new do |spec|
17
+ # spec.name = "rails-erd"
18
+ # spec.rubyforge_project = "rails-erd"
19
+ # spec.summary = "Entity-relationship diagram for your Rails models."
20
+ # spec.description = "Automatically generate an entity-relationship diagram (ERD) for your Rails models."
21
+ #
22
+ # spec.authors = ["Rolf Timmermans"]
23
+ # spec.email = "r.timmermans@voormedia.com"
24
+ # spec.homepage = "http://rails-erd.rubyforge.org/"
25
+ #
26
+ # # Don't bundle examples or website in gem.
27
+ # excluded = Dir["{examples,site}/**/*"]
28
+ # spec.files -= excluded
29
+ # spec.test_files -= excluded
30
+ # end
31
+ #
32
+ # Jeweler::GemcutterTasks.new
33
+ #
34
+ # Jeweler::RubyforgeTasks.new do |rubyforge|
35
+ # rubyforge.doc_task = "rdoc"
36
+ # rubyforge.remote_doc_path = "doc"
37
+ # end
38
+ #
39
+ # Rake::TestTask.new do |test|
40
+ # test.pattern = "test/unit/**/*_test.rb"
41
+ # end
42
+ #
43
+ # task :default => :test
44
+ #
45
+ # begin
46
+ # require "hanna/rdoctask"
47
+ # Rake::RDocTask.new do |rdoc|
48
+ # rdoc.rdoc_files = %w{CHANGES.rdoc LICENSE} + Dir["lib/**/*.rb"]
49
+ # rdoc.title = "Rails ERD – API Documentation"
50
+ # rdoc.rdoc_dir = "rdoc"
51
+ # rdoc.main = "RailsERD"
52
+ # end
53
+ # rescue LoadError
54
+ # end
55
+ #
56
+ # desc "Generate diagrams for bundled examples"
57
+ # task :examples do
58
+ # require File.expand_path("examples/generate", File.dirname(__FILE__))
59
+ # end
60
+ #
61
+ # namespace :examples do
62
+ # task :sfdp do
63
+ # require File.expand_path("examples/sfdp", File.dirname(__FILE__))
64
+ # end
65
+ # end
data/bin/erd ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "rails_erd/cli"
3
+
4
+ RailsERD::CLI.start
data/lib/rails_erd.rb CHANGED
@@ -50,7 +50,7 @@ module RailsERD
50
50
  self.options = ActiveSupport::OrderedOptions[
51
51
  :attributes, :content,
52
52
  :disconnected, true,
53
- :filename, "ERD",
53
+ :filename, "erd",
54
54
  :filetype, :pdf,
55
55
  :indirect, true,
56
56
  :inheritance, false,
@@ -59,6 +59,8 @@ module RailsERD
59
59
  :orientation, :horizontal,
60
60
  :polymorphism, false,
61
61
  :warn, true,
62
- :title, true
62
+ :title, true,
63
+ :exclude, nil,
64
+ :only, nil
63
65
  ]
64
66
  end
@@ -0,0 +1,149 @@
1
+ require "choice"
2
+
3
+ Choice.options do
4
+ separator ""
5
+ separator "Diagram options:"
6
+
7
+ option :title do
8
+ long "--title=TITLE"
9
+ desc "Replace default diagram title with a custom one."
10
+ end
11
+
12
+ option :notation do
13
+ long "--notation=STYLE"
14
+ desc "Diagram notation style, one of simple, bachman, uml or crowsfoot."
15
+ default "simple"
16
+ end
17
+
18
+ option :attributes do
19
+ long "--attributes=TYPE,..."
20
+ desc "Attribute groups to display: content, primary_keys, foreign_keys, timestamps and/or inheritance."
21
+ default "content"
22
+ end
23
+
24
+ option :orientation do
25
+ long "--orientation=ORIENTATION"
26
+ desc "Orientation of diagram, either horizontal (default) or vertical."
27
+ default "orientation"
28
+ end
29
+
30
+ option :inheritance do
31
+ long "--inheritance"
32
+ desc "Display (single table) inheritance relationships."
33
+ end
34
+
35
+ option :polymorphism do
36
+ long "--polymorphism"
37
+ desc "Display polymorphic relationships."
38
+ end
39
+
40
+ option :no_indirect do
41
+ long "--direct"
42
+ desc "Omit indirect relationships (through other entities)."
43
+ end
44
+
45
+ option :no_disconnected do
46
+ long "--connected"
47
+ desc "Omit entities without relationships."
48
+ end
49
+
50
+ separator ""
51
+ separator "Output options:"
52
+
53
+ option :filename do
54
+ long "--filename=FILENAME"
55
+ desc "Basename of the output diagram."
56
+ default "erd"
57
+ end
58
+
59
+ option :filetype do
60
+ long "--filetype=TYPE"
61
+ desc "Output file type. Available types depend on the diagram renderer."
62
+ default "pdf"
63
+ end
64
+
65
+ option :no_markup do
66
+ long "--no-markup"
67
+ desc "Disable markup for enhanced compatibility of .dot output with other applications."
68
+ end
69
+
70
+ option :open do
71
+ long "--open"
72
+ desc "Open the output file after it has been saved."
73
+ end
74
+
75
+ separator ""
76
+ separator "Common options:"
77
+
78
+ option :help do
79
+ long "--help"
80
+ desc "Display this help message."
81
+ end
82
+
83
+ option :debug do
84
+ long "--debug"
85
+ desc "Show stack traces when an error occurs."
86
+ end
87
+
88
+ option :version do
89
+ short "-v"
90
+ long "--version"
91
+ desc "Show version and quit."
92
+ action do
93
+ require "rails_erd/version"
94
+ $stderr.puts RailsERD::BANNER
95
+ exit
96
+ end
97
+ end
98
+ end
99
+
100
+ module RailsERD
101
+ class CLI
102
+ attr_reader :path, :options
103
+
104
+ class << self
105
+ def start
106
+ path = Choice.rest.first || Dir.pwd
107
+ options = Choice.choices.each_with_object({}) do |(key, value), opts|
108
+ if key.start_with? "no_"
109
+ opts[key.gsub("no_", "").to_sym] = !value
110
+ elsif value.to_s.include? ","
111
+ opts[key.to_sym] = value.split(",").map(&:to_sym)
112
+ else
113
+ opts[key.to_sym] = value
114
+ end
115
+ end
116
+ new(path, options).start
117
+ end
118
+ end
119
+
120
+ def initialize(path, options)
121
+ @path, @options = path, options
122
+ require "rails_erd/diagram/graphviz"
123
+ end
124
+
125
+ def start
126
+ load_application
127
+ create_diagram
128
+ rescue Exception => e
129
+ $stderr.puts "Failed: #{e.class}: #{e.message}"
130
+ $stderr.puts e.backtrace.map { |t| " from #{t}" } if options[:debug]
131
+ end
132
+
133
+ private
134
+
135
+ def load_application
136
+ $stderr.puts "Loading application in '#{File.basename(path)}'..."
137
+ # TODO: Add support for different kinds of environment.
138
+ require "#{path}/config/environment"
139
+ Rails.application.eager_load!
140
+ end
141
+
142
+ def create_diagram
143
+ $stderr.puts "Generating entity-relationship diagram for #{ActiveRecord::Base.descendants.length} models..."
144
+ file = RailsERD::Diagram::Graphviz.create(options)
145
+ $stderr.puts "Diagram saved to '#{file}'."
146
+ `open #{file}` if options[:open]
147
+ end
148
+ end
149
+ end
@@ -3,7 +3,7 @@ require "rails_erd/domain"
3
3
  module RailsERD
4
4
  # This class is an abstract class that will process a domain model and
5
5
  # allows easy creation of diagrams. To implement a new diagram type, derive
6
- # from this class and override +process_entity+, +process_relationship+,
6
+ # from this class and override +process_entity+, +process_relationship+,
7
7
  # and (optionally) +save+.
8
8
  #
9
9
  # As an example, a diagram class that generates code that can be used with
@@ -73,13 +73,13 @@ module RailsERD
73
73
  def create(options = {})
74
74
  new(Domain.generate(options), options).create
75
75
  end
76
-
76
+
77
77
  protected
78
-
78
+
79
79
  def setup(&block)
80
80
  callbacks[:setup] = block
81
81
  end
82
-
82
+
83
83
  def each_entity(&block)
84
84
  callbacks[:each_entity] = block
85
85
  end
@@ -91,7 +91,7 @@ module RailsERD
91
91
  def each_specialization(&block)
92
92
  callbacks[:each_specialization] = block
93
93
  end
94
-
94
+
95
95
  def save(&block)
96
96
  callbacks[:save] = block
97
97
  end
@@ -105,7 +105,7 @@ module RailsERD
105
105
 
106
106
  # The options that are used to create this diagram.
107
107
  attr_reader :options
108
-
108
+
109
109
  # The domain that this diagram represents.
110
110
  attr_reader :domain
111
111
 
@@ -113,13 +113,13 @@ module RailsERD
113
113
  def initialize(domain, options = {})
114
114
  @domain, @options = domain, RailsERD.options.merge(options)
115
115
  end
116
-
116
+
117
117
  # Generates and saves the diagram, returning the result of +save+.
118
118
  def create
119
119
  generate
120
120
  save
121
121
  end
122
-
122
+
123
123
  # Generates the diagram, but does not save the output. It is called
124
124
  # internally by Diagram#create.
125
125
  def generate
@@ -137,19 +137,21 @@ module RailsERD
137
137
  instance_exec relationship, &callbacks[:each_relationship]
138
138
  end
139
139
  end
140
-
140
+
141
141
  def save
142
142
  instance_eval &callbacks[:save]
143
143
  end
144
-
144
+
145
145
  private
146
-
146
+
147
147
  def callbacks
148
148
  @callbacks ||= self.class.send(:callbacks)
149
149
  end
150
-
150
+
151
151
  def filtered_entities
152
152
  @domain.entities.reject { |entity|
153
+ options.exclude && entity.model && [options.exclude].flatten.include?(entity.name.to_sym) or
154
+ options.only && entity.model && ![options.only].flatten.include?(entity.name.to_sym) or
153
155
  !options.inheritance && entity.specialized? or
154
156
  !options.polymorphism && entity.generalized? or
155
157
  !options.disconnected && entity.disconnected?
@@ -157,20 +159,20 @@ module RailsERD
157
159
  raise "No entities found; create your models first!" if entities.empty?
158
160
  end
159
161
  end
160
-
162
+
161
163
  def filtered_relationships
162
164
  @domain.relationships.reject { |relationship|
163
165
  !options.indirect && relationship.indirect?
164
166
  }
165
167
  end
166
-
168
+
167
169
  def filtered_specializations
168
170
  @domain.specializations.reject { |specialization|
169
171
  !options.inheritance && specialization.inheritance? or
170
172
  !options.polymorphism && specialization.polymorphic?
171
173
  }
172
174
  end
173
-
175
+
174
176
  def filtered_attributes(entity)
175
177
  entity.attributes.reject { |attribute|
176
178
  # Select attributes that satisfy the conditions in the :attributes option.
@@ -178,7 +180,7 @@ module RailsERD
178
180
  [*options.attributes].none? { |type| attribute.send(:"#{type.to_s.chomp('s')}?") }
179
181
  }
180
182
  end
181
-
183
+
182
184
  def warn(message)
183
185
  puts "Warning: #{message}" if options.warn
184
186
  end