modaldiagrams 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'modalsettings'
4
+ gem 'modalsupport', '>= 0.9.2'
5
+
6
+
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development do
10
+ gem "shoulda", ">= 0"
11
+ gem "rdoc", "~> 3.12"
12
+ gem "bundler", "~> 1.1.0"
13
+ gem "jeweler", "~> 1.8.4"
14
+ gem 'modalfields', '>= 1.2.0'
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,110 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.2.8)
5
+ actionpack (= 3.2.8)
6
+ mail (~> 2.4.4)
7
+ actionpack (3.2.8)
8
+ activemodel (= 3.2.8)
9
+ activesupport (= 3.2.8)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ journey (~> 1.0.4)
13
+ rack (~> 1.4.0)
14
+ rack-cache (~> 1.2)
15
+ rack-test (~> 0.6.1)
16
+ sprockets (~> 2.1.3)
17
+ activemodel (3.2.8)
18
+ activesupport (= 3.2.8)
19
+ builder (~> 3.0.0)
20
+ activerecord (3.2.8)
21
+ activemodel (= 3.2.8)
22
+ activesupport (= 3.2.8)
23
+ arel (~> 3.0.2)
24
+ tzinfo (~> 0.3.29)
25
+ activeresource (3.2.8)
26
+ activemodel (= 3.2.8)
27
+ activesupport (= 3.2.8)
28
+ activesupport (3.2.8)
29
+ i18n (~> 0.6)
30
+ multi_json (~> 1.0)
31
+ arel (3.0.2)
32
+ builder (3.0.0)
33
+ erubis (2.7.0)
34
+ git (1.2.5)
35
+ hike (1.2.1)
36
+ i18n (0.6.1)
37
+ jeweler (1.8.4)
38
+ bundler (~> 1.0)
39
+ git (>= 1.2.5)
40
+ rake
41
+ rdoc
42
+ journey (1.0.4)
43
+ json (1.7.5)
44
+ mail (2.4.4)
45
+ i18n (>= 0.4.0)
46
+ mime-types (~> 1.16)
47
+ treetop (~> 1.4.8)
48
+ mime-types (1.19)
49
+ modalfields (1.2.0)
50
+ activerecord (>= 2.3.5)
51
+ activesupport (>= 2.3.5)
52
+ rails (>= 2.3.0)
53
+ modalsettings (1.0.0)
54
+ modalsupport (>= 0.8.1)
55
+ modalsupport (0.9.2)
56
+ multi_json (1.3.6)
57
+ polyglot (0.3.3)
58
+ rack (1.4.1)
59
+ rack-cache (1.2)
60
+ rack (>= 0.4)
61
+ rack-ssl (1.3.2)
62
+ rack
63
+ rack-test (0.6.1)
64
+ rack (>= 1.0)
65
+ rails (3.2.8)
66
+ actionmailer (= 3.2.8)
67
+ actionpack (= 3.2.8)
68
+ activerecord (= 3.2.8)
69
+ activeresource (= 3.2.8)
70
+ activesupport (= 3.2.8)
71
+ bundler (~> 1.0)
72
+ railties (= 3.2.8)
73
+ railties (3.2.8)
74
+ actionpack (= 3.2.8)
75
+ activesupport (= 3.2.8)
76
+ rack-ssl (~> 1.3.2)
77
+ rake (>= 0.8.7)
78
+ rdoc (~> 3.4)
79
+ thor (>= 0.14.6, < 2.0)
80
+ rake (0.9.2.2)
81
+ rdoc (3.12)
82
+ json (~> 1.4)
83
+ shoulda (3.1.1)
84
+ shoulda-context (~> 1.0)
85
+ shoulda-matchers (~> 1.2)
86
+ shoulda-context (1.0.0)
87
+ shoulda-matchers (1.3.0)
88
+ activesupport (>= 3.0.0)
89
+ sprockets (2.1.3)
90
+ hike (~> 1.2)
91
+ rack (~> 1.0)
92
+ tilt (~> 1.1, != 1.3.0)
93
+ thor (0.16.0)
94
+ tilt (1.3.3)
95
+ treetop (1.4.10)
96
+ polyglot
97
+ polyglot (>= 0.3.1)
98
+ tzinfo (0.3.33)
99
+
100
+ PLATFORMS
101
+ ruby
102
+
103
+ DEPENDENCIES
104
+ bundler (~> 1.1.0)
105
+ jeweler (~> 1.8.4)
106
+ modalfields (>= 1.2.0)
107
+ modalsettings
108
+ modalsupport (>= 0.9.2)
109
+ rdoc (~> 3.12)
110
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Javier Goizueta
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,20 @@
1
+ = modaldiagrams
2
+
3
+ This gem provides Rake tasks for diagramming ActiveRecord databases.
4
+ The diagrams are generated as Graphviz dot files. Additional taks generate PostScript, PNG or PDF output using GhostView.
5
+
6
+ == Contributing to modaldiagrams
7
+
8
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
9
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
10
+ * Fork the project.
11
+ * Start a feature/bugfix branch.
12
+ * Commit and push until you are happy with your contribution.
13
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
14
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2012 Javier Goizueta. See LICENSE.txt for
19
+ further details.
20
+
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "modaldiagrams"
18
+ gem.homepage = "http://github.com/jgoizueta/modaldiagrams"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{DB diagramming tool fo Rails ActiveRecord applications}
21
+ gem.description = %Q{modaldiagrams provides Rake tasks for diagramming ActiveRecord databases. It generates Graphviz dot files.}
22
+ gem.email = "jgoizueta@gmail.com"
23
+ gem.authors = ["Javier Goizueta"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'rdoc/task'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "modaldiagrams #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ TODO
2
+ * Write tests (use simple demo data model whose diagrams will serve as a generic diagram legend as well)
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,277 @@
1
+ # ActiveRecord DB Diagrams
2
+ # Configuration parameters can be changed by writing a file named config/db_diagram.yml
3
+
4
+ module ModalDiagrams
5
+
6
+ # Field type abbreviations
7
+ TYPE = {
8
+ :date=>'d',
9
+ :datetime=>'dt',
10
+ :timestamp=>'ts',
11
+ :boolean=>'b',
12
+ :integer=>'i',
13
+ :string=>'s',
14
+ :text=>'tx',
15
+ :float=>'f',
16
+ :decimal=>'d',
17
+ :geometry=>'g'
18
+ }
19
+
20
+ class <<self
21
+
22
+ def enable_clusters
23
+ if defined?(::Rails)
24
+ ::ActiveRecord::Base.class_eval do
25
+ def self.cluster(name=nil)
26
+ if name
27
+ @cluster_name = name
28
+ else
29
+ @cluster_name
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def generate(cfg)
37
+
38
+ classes = {""=>[]} # assoc cluster name ("" for no cluster) to array of class definitions
39
+ relations = [] # array of relation defitions
40
+ n_m = [] # this is to avoid duplicating n:m relations
41
+ rep = [] # this is to avoid multiple relations between two models
42
+ # and the next is to draw separate diagrams per cluster
43
+ cluster_classes = {} # assoc cluster name to array of class names
44
+ relation_classes = [] # each element is the 2-element array of class names of the corresponding relation in relations
45
+
46
+ models = dbmodels
47
+
48
+ models.each do |cls|
49
+ if cls.respond_to?(:reflect_on_all_associations) && ActiveRecord::Base.connection.table_exists?(cls.table_name)
50
+ # Note: Don't use content_columns ignores columns ending with _id which I use for enum fields
51
+ columns = cls.columns.reject { |c| c.primary || c.name =~ /(_count)$/ || c.name == cls.inheritance_column || c.name =~ /^(created_at|updated_at)$/ }.map{|c| "#{c.name} : #{TYPE[c.type]}"}
52
+ columns_to_ignore = cls.reflect_on_all_associations.map{|a|
53
+ cols = []
54
+ if a.macro == :belongs_to
55
+ cols << assoc_foreign_key(a)
56
+ cols << assoc_foreign_type(a) if a.options[:polymorphic]
57
+ end
58
+ cols
59
+ }.flatten.compact.uniq
60
+ columns.reject!{|c| c.split(':').first.strip.in? columns_to_ignore}
61
+ if cfg.sti_fields && cls.respond_to?(:fields_info) && cls.fields_info!=:omitted
62
+ columns.reject!{|c| !c.split(':').first.strip.in? cls.fields_info.map{|c| c.name.to_s}}
63
+ end
64
+ columns = columns.to(cfg.max_attributes) + ['...'] if columns.size > cfg.max_attributes
65
+ # columns.reject! do |cname|
66
+ # cname.match(/_id\Z/) || cname.match(/_type\Z/)
67
+ # end
68
+ # arrowhead,arrowtail=none, normal, inv, dot, odot, invdot, invodot, tee,
69
+ # empty, invempty, open(2,3,n), halfopen, diamond, odiamond, box, obox, crow.
70
+ if cls.respond_to?(:cluster)
71
+ cluster = cls.cluster.to_s
72
+ classes[cluster] ||= []
73
+ else
74
+ cluster = ""
75
+ end
76
+ classes[cluster] << %{"#{cls}" [shape=Mrecord, label="{#{cls}|#{columns.join('\\l')}\\l}"]}
77
+ cluster_classes[cluster] ||= []
78
+ cluster_classes[cluster] << cls.to_s
79
+ cls.reflect_on_all_associations.each do |assoc|
80
+ target,type = nil,nil
81
+ case assoc.macro
82
+ when :has_many
83
+ unless assoc.options[:through]
84
+ target = assoc.class_name
85
+ type = :one_to_many
86
+ if !cfg.show_multiple && rep.include?([cls.to_s, target.to_s])
87
+ target = type = nil
88
+ else
89
+ rep << [cls.to_s,target.to_s]
90
+ end
91
+ end
92
+ when :has_one
93
+ target = assoc.class_name
94
+ type = :one_to_one
95
+ when :has_and_belongs_to_many
96
+ target = assoc.class_name
97
+ type = :many_to_many
98
+ if n_m.include?([target.to_s, cls.to_s])
99
+ target = type = nil
100
+ else
101
+ n_m << [cls.to_s,target.to_s]
102
+ end
103
+ end
104
+ if target
105
+ pk = assoc_foreign_key(assoc)
106
+ # detect specially named associations (usually polymorphi) and label it
107
+ if pk != cls.to_s.underscore+"_id"
108
+ label = pk.to_s
109
+ label = label[0..-4] if label[-3..-1]=='_id'
110
+ if label.size<=15
111
+ label = "headlabel=#{label}, "
112
+ else
113
+ label = nil
114
+ end
115
+ else
116
+ label = nil
117
+ end
118
+ # detect polymorphic associations to use a different symbol
119
+ poly = false
120
+ if iassoc = target.constantize.reflect_on_all_associations.detect{|a| !a.options[:through] && pk==assoc_foreign_key(a)}
121
+ if iassoc.options[:polymorphic]
122
+ poly = true
123
+ end
124
+ end
125
+ #puts "#{cls} -#{type}-> #{target}"
126
+ case type
127
+ when :one_to_one
128
+ tail = "none"
129
+ head = poly ? "obox" : "tee" # mark the end with the foreign key
130
+ when :one_to_many
131
+ tail = "none"
132
+ head = poly ? "odot" : "dot"
133
+ when :many_to_many
134
+ tail = "dot"
135
+ head = "dot"
136
+ end
137
+ samehead = (cfg.unified_polymorphic && label) ? %{, samehead="#{label}"} : ''
138
+ label = nil if cfg.no_association_labels
139
+ relations << %{"#{cls}" -> "#{target}" [arrowtail=#{tail}, arrowhead=#{head}#{samehead} #{label}dir=both]}
140
+ relation_classes << [cls.to_s, target.to_s]
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ if cfg.show_sti
147
+ sti_classes.each do |sti_class|
148
+ cls = sti_class.base_class
149
+ if cls.respond_to?(:cluster)
150
+ cluster = cls.cluster.to_s
151
+ else
152
+ cluster = ""
153
+ end
154
+ if cfg.sti_fields && sti_class.respond_to?(:fields_info) && sti_class.fields_info!=:omitted
155
+ columns = sti_class.fields_info.map{|c| "#{c.name} : #{TYPE[c.type]}"}
156
+ columns = columns.to(cfg.max_attributes) + ['...'] if columns.size > cfg.max_attributes
157
+ else
158
+ columns = nil
159
+ end
160
+ classes[cluster] ||= []
161
+ classes[cluster] << %{"#{sti_class}" [shape=Mrecord, label="{#{sti_class}\\l}"]}
162
+ cluster_classes[cluster] ||= []
163
+ cluster_classes[cluster] << sti_class.to_s
164
+ if columns
165
+ classes[cluster] << %{"#{sti_class}" [shape=Mrecord, label="{#{sti_class}|#{columns.join('\\l')}\\l}"]}
166
+ end
167
+ base_class = sti_class.superclass
168
+ relations << %{"#{base_class}" -> "#{sti_class}" [arrowtail=onormal, arrowhead=none, dir=both]}
169
+ relation_classes << [base_class.to_s, sti_class.to_s]
170
+ end
171
+ end
172
+
173
+ fn = Rails.root.join('db/diagrams/diagram.dot')
174
+ mkdir_p fn.dirname
175
+ File.open(fn,'w') do |f|
176
+ add_diagram_header f
177
+ cluster_id = 0
178
+ all_classes = []
179
+ classes.keys.each do |cluster|
180
+ next if cluster.in? cfg.clusters_not_shown_on_main_diagram
181
+ all_classes += cluster_classes[cluster]
182
+ cluster_id += 1
183
+ add_diagram_classes f, classes[cluster], cluster, cluster_id, cfg.show_cluster_boxes
184
+ end
185
+ add_diagram_relations f, relations, relation_classes, all_classes, cfg.show_external
186
+ add_diagram_footer f
187
+ end
188
+ classes.keys.each do |cluster|
189
+ #next if cluster.blank?
190
+ fn = "db/diagrams/diagram_#{cluster.downcase}.dot"
191
+ File.open(fn,'w') do |f|
192
+ add_diagram_header f
193
+ add_diagram_classes f, classes[cluster]
194
+ add_diagram_relations f, relations, relation_classes, cluster_classes[cluster], cfg.show_external
195
+ add_diagram_footer f
196
+ end
197
+ end
198
+ puts "The diagrams have been written to #{fn}"
199
+
200
+ end
201
+
202
+
203
+ private
204
+
205
+ # return ActiveRecord classes corresponding to tables, without STI derived classes, but including indirectly
206
+ # derived classes that do have their own tables (to achieve this we use the convention that in such cases
207
+ # the base class, directly derived from ActiveRecord::Base has a nil table_name)
208
+ def dbmodels
209
+ models = Dir.glob(File.join(Rails.root,"app/models/**/*.rb"))\
210
+ .map{|f| File.basename(f).chomp(".rb").camelize.constantize}\
211
+ .select{|c| has_table(c)}\
212
+ .reject{|c| has_table(c.superclass)}
213
+ models += ActiveRecord::Base.send(:subclasses).reject{|c| c.name.starts_with?('CGI::') || !has_table(c) || has_table(c.superclass)}
214
+ models.uniq
215
+ end
216
+
217
+ def sti_classes
218
+ models = Dir.glob(File.join(Rails.root,"app/models/**/*.rb"))\
219
+ .map{|f| File.basename(f).chomp(".rb").camelize.constantize}\
220
+ .select{|c| has_table(c) && c.base_class!=c}
221
+ models += ActiveRecord::Base.send(:subclasses).reject{|c| c.name.starts_with?('CGI::') || !has_table(c)}.select{|c| has_table(c) && c.base_class!=c}
222
+ models.uniq
223
+ end
224
+
225
+ def assoc_foreign_key(assoc)
226
+ # Up to ActiveRecord 3.1 we had primary_key_name in AssociationReflection; not it is foreign_key
227
+ assoc.respond_to?(:primary_key_name) ? assoc.primary_key_name : assoc.foreign_key
228
+ end
229
+
230
+ def assoc_foreign_type(assoc)
231
+ assoc.respond_to?(:foreign_type) ? assoc.foreign_type : assoc.options[:foreign_key]
232
+ end
233
+
234
+ def has_table(cls)
235
+ (cls!=ActiveRecord::Base) && cls.respond_to?(:table_name) && !cls.table_name.blank?
236
+ end
237
+
238
+ def add_diagram_header(f)
239
+ f.puts "digraph models_diagram {"
240
+ f.puts " graph[overlap=false, splines=true]"
241
+ f.puts " edge[labeldistance=2.5, labelfloat=true, labelfontname=Helvetica, decorate=false, labelangle=-30, fontsize=10, fontcolor=gray35]"
242
+ end
243
+
244
+ def add_diagram_classes(f, classes, cluster="", cluster_id=nil, show_cluster_boxes=false)
245
+ if cluster==""
246
+ f.puts classes.join("\n")
247
+ elsif cluster.downcase==cluster || !show_cluster_boxes
248
+ f.puts %<subgraph #{cluster_id} {\n #{classes.join("\n ")}\n}>
249
+ else
250
+ f.puts %<subgraph cluster_#{cluster_id} { label="#{cluster}"\n #{classes.join("\n ")}\n}>
251
+ end
252
+ end
253
+
254
+ def add_diagram_relations(f, relations, relation_classes, inner_classes, show_external)
255
+ relations.each_index do |i|
256
+ relation = relations[i]
257
+ is_internal = relation_classes[i].all?{|c| c.in? inner_classes}
258
+ is_external = relation_classes[i].any?{|c| c.in? inner_classes} && !is_internal
259
+ if show_external
260
+ show_relation = is_internal || is_external
261
+ unless is_internal
262
+ relation = relation.sub('arrowtail', 'color="gray", arrowtail')
263
+ end
264
+ else
265
+ show_relation = is_internal
266
+ end
267
+ f.puts relation if show_relation
268
+ end
269
+ end
270
+
271
+ def add_diagram_footer(f)
272
+ f.puts "}\n"
273
+ end
274
+
275
+ end
276
+
277
+ end
@@ -0,0 +1,19 @@
1
+ module ModalDiagrams
2
+
3
+ def self.parameters
4
+ @settings ||= Settings[
5
+ # Default values
6
+ :max_attributes => 24, # maximum number of attributes shown in a class (table)
7
+ :clusters_not_shown_on_main_diagram => [], # clusters not shown in the main diagram
8
+ :show_external => true, # show associations to classes from other clusters in cluster diagrams
9
+ :show_cluster_boxes => false, # display cluster names capitalized inside a box (good for dot; bad for neato)
10
+ :show_multiple => true, # show multiple associations between two classes
11
+ :show_sti => true, # show STI classes
12
+ :sti_fields => true, # show fields of STI classes where declared if using modalfields
13
+ :unified_polymorphic => false, # unify the circled end of polymorphic associations
14
+ :no_association_labels=>false, # don't show association labels
15
+ :output_tools => %w{dot fdp neato} # graphviz styles (tools) used whe generating output (ps/png/pdf)
16
+ ].merge Settings.load(Rails.root.join('config','db_diagram.yml'))
17
+ end
18
+
19
+ end
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), '..', 'tasks', '**/*.rake')].each { |f| load f }
@@ -0,0 +1,13 @@
1
+ require 'modaldiagrams/parameters'
2
+ require 'modaldiagrams/modaldiagrams'
3
+
4
+ if defined?(Rails) && Rails.respond_to?(:version)
5
+ if Rails.version.split('.').first.to_i > 2
6
+ class BackupTask < Rails::Railtie
7
+ rake_tasks do
8
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |f| load f }
9
+ end
10
+ end
11
+ end
12
+ ModalDiagrams.enable_clusters if defined?(ActiveRecord::Base)
13
+ end
@@ -0,0 +1,15 @@
1
+ namespace :db do
2
+
3
+ desc "Generate DB diagrams (in dot format)"
4
+ task :diagrams => [:environment] do
5
+
6
+ cfg = ModalDiagrams.parameters
7
+ puts "Using parameters:"
8
+ puts cfg.to_yaml + "\n"
9
+ puts "To change the parameters create or edit a file named config/modal_diagrams.yml"
10
+
11
+ ModalDiagrams.generate cfg
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,20 @@
1
+ namespace :db do
2
+ namespace :diagrams do
3
+
4
+ desc "Generate DB diagrams and convert to PDF with Graphviz and Ghostview"
5
+ task :pdf => 'db:diagrams:ps' do
6
+ ModalDiagrams.parameters.output_tools.each do |cmd|
7
+ in_dir = Rails.root.join("db/diagrams/#{cmd}_ps")
8
+ out_dir = Rails.root.join("db/diagrams/#{cmd}_pdf")
9
+ mkdir_p out_dir
10
+ Dir[in_dir.join('*.ps')].each do |fn|
11
+ fn = Pathname(fn)
12
+ out_fn = out_dir.join(fn.basename.sub_ext('.pdf'))
13
+ `ps2pdf #{fn} #{out_fn}`
14
+ end
15
+ puts "Output has been generated in #{out_dir}"
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ namespace :db do
2
+ namespace :diagrams do
3
+
4
+ desc "Generate DB diagrams and convert to PNG with Graphviz and Ghostview"
5
+ task :png => 'db:diagrams:ps' do
6
+ ModalDiagrams.parameters.output_tools.each do |cmd|
7
+ in_dir = Rails.root.join("db/diagrams/#{cmd}_ps")
8
+ out_dir = Rails.root.join("db/diagrams/#{cmd}_png")
9
+ mkdir_p out_dir
10
+ Dir[in_dir.join('*.ps')].each do |fn|
11
+ fn = Pathname(fn)
12
+ out_fn = out_dir.join(fn.basename.sub_ext('.png'))
13
+ `gs -q -dNOPAUSE -dBATCH -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=png16m -sOutputFile=#{out_fn} #{fn}`
14
+ end
15
+ puts "Output has been generated in #{out_dir}"
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ namespace :db do
2
+ namespace :diagrams do
3
+
4
+ desc "Generate DB diagrams and convert to PS with Graphviz"
5
+ task :ps => 'db:diagrams' do
6
+ ModalDiagrams.parameters.output_tools.each do |cmd|
7
+ out_dir = Rails.root.join("db/diagrams/#{cmd}_ps")
8
+ mkdir_p out_dir
9
+ Dir[Rails.root.join('db/diagrams/*.dot')].each do |fn|
10
+ fn = Pathname(fn)
11
+ out_fn = out_dir.join(fn.basename.sub_ext('.ps'))
12
+ `#{cmd} #{fn} -o#{out_fn} -Tps2`
13
+ end
14
+ puts "Output has been generated in #{out_dir}"
15
+ end
16
+ end
17
+
18
+ end
19
+ end
data/lib/tasks.rb ADDED
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), '..', 'tasks', '**/*.rake')].each { |f| load f }
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "modaldiagrams"
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Javier Goizueta"]
12
+ s.date = "2012-09-05"
13
+ s.description = "modaldiagrams provides Rake tasks for diagramming ActiveRecord databases. It generates Graphviz dot files."
14
+ s.email = "jgoizueta@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc",
18
+ "TODO"
19
+ ]
20
+ s.files = [
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "TODO",
27
+ "VERSION",
28
+ "lib/modaldiagrams.rb",
29
+ "lib/modaldiagrams/modaldiagrams.rb",
30
+ "lib/modaldiagrams/parameters.rb",
31
+ "lib/modaldiagrams/tasks.rb",
32
+ "lib/tasks.rb",
33
+ "lib/tasks/diagrams.rake",
34
+ "lib/tasks/diagrams_pdf.rake",
35
+ "lib/tasks/diagrams_png.rake",
36
+ "lib/tasks/diagrams_ps.rake",
37
+ "modaldiagrams.gemspec"
38
+ ]
39
+ s.homepage = "http://github.com/jgoizueta/modaldiagrams"
40
+ s.licenses = ["MIT"]
41
+ s.require_paths = ["lib"]
42
+ s.rubygems_version = "1.8.23"
43
+ s.summary = "DB diagramming tool fo Rails ActiveRecord applications"
44
+
45
+ if s.respond_to? :specification_version then
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
+ s.add_runtime_dependency(%q<modalsettings>, [">= 0"])
50
+ s.add_runtime_dependency(%q<modalsupport>, [">= 0.9.2"])
51
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
52
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
53
+ s.add_development_dependency(%q<bundler>, ["~> 1.1.0"])
54
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
55
+ s.add_development_dependency(%q<modalfields>, [">= 1.2.0"])
56
+ else
57
+ s.add_dependency(%q<modalsettings>, [">= 0"])
58
+ s.add_dependency(%q<modalsupport>, [">= 0.9.2"])
59
+ s.add_dependency(%q<shoulda>, [">= 0"])
60
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
61
+ s.add_dependency(%q<bundler>, ["~> 1.1.0"])
62
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
63
+ s.add_dependency(%q<modalfields>, [">= 1.2.0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<modalsettings>, [">= 0"])
67
+ s.add_dependency(%q<modalsupport>, [">= 0.9.2"])
68
+ s.add_dependency(%q<shoulda>, [">= 0"])
69
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
70
+ s.add_dependency(%q<bundler>, ["~> 1.1.0"])
71
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
72
+ s.add_dependency(%q<modalfields>, [">= 1.2.0"])
73
+ end
74
+ end
75
+
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: modaldiagrams
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Javier Goizueta
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: modalsettings
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: modalsupport
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.9.2
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.9.2
46
+ - !ruby/object:Gem::Dependency
47
+ name: shoulda
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rdoc
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '3.12'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '3.12'
78
+ - !ruby/object:Gem::Dependency
79
+ name: bundler
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.1.0
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.1.0
94
+ - !ruby/object:Gem::Dependency
95
+ name: jeweler
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 1.8.4
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 1.8.4
110
+ - !ruby/object:Gem::Dependency
111
+ name: modalfields
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: 1.2.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: 1.2.0
126
+ description: modaldiagrams provides Rake tasks for diagramming ActiveRecord databases.
127
+ It generates Graphviz dot files.
128
+ email: jgoizueta@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files:
132
+ - LICENSE.txt
133
+ - README.rdoc
134
+ - TODO
135
+ files:
136
+ - Gemfile
137
+ - Gemfile.lock
138
+ - LICENSE.txt
139
+ - README.rdoc
140
+ - Rakefile
141
+ - TODO
142
+ - VERSION
143
+ - lib/modaldiagrams.rb
144
+ - lib/modaldiagrams/modaldiagrams.rb
145
+ - lib/modaldiagrams/parameters.rb
146
+ - lib/modaldiagrams/tasks.rb
147
+ - lib/tasks.rb
148
+ - lib/tasks/diagrams.rake
149
+ - lib/tasks/diagrams_pdf.rake
150
+ - lib/tasks/diagrams_png.rake
151
+ - lib/tasks/diagrams_ps.rake
152
+ - modaldiagrams.gemspec
153
+ homepage: http://github.com/jgoizueta/modaldiagrams
154
+ licenses:
155
+ - MIT
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ segments:
167
+ - 0
168
+ hash: -3401625637363987072
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ requirements: []
176
+ rubyforge_project:
177
+ rubygems_version: 1.8.23
178
+ signing_key:
179
+ specification_version: 3
180
+ summary: DB diagramming tool fo Rails ActiveRecord applications
181
+ test_files: []