railroad 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,5 +1,20 @@
1
+ Version 0.5.0 (may 10 2008)
2
+ - Changed model relationships representation (feature request #10898)
3
+ - Added support for plugins models (-p) (feature request #12742 by
4
+ Chris Richards). Thanks to Elliot Smith.
5
+ - Added support for irregular inflexions (from patch #12384). Thanks
6
+ to Juan Ignacio Pumarino.
7
+ - Added hidding of magic fields (--hide-magic) (from patch #13351)
8
+ Thanks to Hajime Baba.
9
+ - Added -r option to set the application root path (request #12801).
10
+ - The -e flag now requires full path to excluded files.
11
+ - Added support for state machine diagram ("acts as state machine" plugin).
12
+ Thanks to Ana Nelson (she did all the work!).
13
+
14
+
1
15
  Version 0.4.1 (may 9 2008)
2
- - Fix a bug (class name treated as String).
16
+ - Fix bug #17852 (class name treated as String).
17
+
3
18
 
4
19
  Version 0.4.0 (apr 25 2007)
5
20
  - Draw inheritance edges in reverse way
data/README CHANGED
@@ -18,9 +18,7 @@ controller diagrams are best processed using neato.
18
18
  Common options:
19
19
  -b, --brief Generate compact diagram
20
20
  (no attributes nor methods)
21
- -e, --exclude file1[,fileN] Exclude files
22
- (relative path to 'app/models/' or
23
- 'app/controllers/')
21
+ -e, --exclude file1[,fileN] Exclude given files
24
22
  -i, --inheritance Include inheritance relations
25
23
  -l, --label Add a label with diagram information
26
24
  (type, date, migration, version)
@@ -31,9 +29,11 @@ Common options:
31
29
  Models diagram options:
32
30
  -a, --all Include all models
33
31
  (not only ActiveRecord::Base derived)
32
+ --hide-magic Hide magic field names
34
33
  --hide-types Hide attributes type
35
34
  -j, --join Concentrate edges
36
35
  -m, --modules Include modules
36
+ -p, --plugins-models Include plugins models
37
37
  -t, --transitive Include transitive associations
38
38
  (through inheritance)
39
39
 
@@ -50,6 +50,7 @@ Other options:
50
50
 
51
51
  -M, --models Generate models diagram
52
52
  -C, --controllers Generate controllers diagram
53
+ -A, --aasm Generate "acts as state machine" diagram
53
54
 
54
55
 
55
56
  == Examples
@@ -6,7 +6,7 @@
6
6
  # RailRoad generates models and controllers diagrams in DOT language
7
7
  # for a Rails application.
8
8
  #
9
- # Copyright 2007 - Javier Smaldone (http://www.smaldone.com.ar)
9
+ # Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
10
10
  #
11
11
  # This program is free software; you can redistribute it and/or modify
12
12
  # it under the terms of the GNU General Public License as published by
@@ -16,21 +16,28 @@
16
16
 
17
17
  APP_NAME = "railroad"
18
18
  APP_HUMAN_NAME = "RailRoad"
19
- APP_VERSION = [0,4,1]
20
- COPYRIGHT = "Copyright (C) 2007 Javier Smaldone"
19
+ APP_VERSION = [0,5,0]
20
+ COPYRIGHT = "Copyright (C) 2007-2008 Javier Smaldone"
21
21
 
22
22
  require 'railroad/options_struct'
23
23
  require 'railroad/models_diagram'
24
24
  require 'railroad/controllers_diagram'
25
+ require 'railroad/aasm_diagram'
25
26
 
26
27
  options = OptionsStruct.new
27
28
 
28
29
  options.parse ARGV
29
30
 
31
+ old_dir = Dir.pwd
32
+
33
+ Dir.chdir(options.root) if options.root != ''
34
+
30
35
  if options.command == 'models'
31
36
  diagram = ModelsDiagram.new options
32
37
  elsif options.command == 'controllers'
33
38
  diagram = ControllersDiagram.new options
39
+ elsif options.command == 'aasm'
40
+ diagram = AasmDiagram.new options
34
41
  else
35
42
  STDERR.print "Error: You must supply a command\n" +
36
43
  " (try #{APP_NAME} -h)\n\n"
@@ -38,4 +45,8 @@ else
38
45
  end
39
46
 
40
47
  diagram.generate
48
+
49
+ Dir.chdir(old_dir)
50
+
41
51
  diagram.print
52
+
@@ -0,0 +1,81 @@
1
+ # RailRoad - RoR diagrams generator
2
+ # http://railroad.rubyforge.org
3
+ #
4
+ # Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
5
+ # See COPYING for more details
6
+
7
+ # AASM code provided by Ana Nelson (http://ananelson.com/)
8
+
9
+ require 'railroad/app_diagram'
10
+
11
+ # Diagram for Acts As State Machine
12
+ class AasmDiagram < AppDiagram
13
+
14
+ def initialize(options)
15
+ #options.exclude.map! {|e| e = "app/models/" + e}
16
+ super options
17
+ @graph.diagram_type = 'Models'
18
+ # Processed habtm associations
19
+ @habtm = []
20
+ end
21
+
22
+ # Process model files
23
+ def generate
24
+ STDERR.print "Generating AASM diagram\n" if @options.verbose
25
+ files = Dir.glob("app/models/**/*.rb")
26
+ files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
27
+ files -= @options.exclude
28
+ files.each do |f|
29
+ process_class extract_class_name(f).constantize
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ # Load model classes
36
+ def load_classes
37
+ begin
38
+ disable_stdout
39
+ files = Dir.glob("app/models/**/*.rb")
40
+ files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
41
+ files -= @options.exclude
42
+ files.each {|m| require m }
43
+ enable_stdout
44
+ rescue LoadError
45
+ enable_stdout
46
+ print_error "model classes"
47
+ raise
48
+ end
49
+ end # load_classes
50
+
51
+ # Process a model class
52
+ def process_class(current_class)
53
+
54
+ STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
55
+
56
+ # Only interested in acts_as_state_machine models.
57
+ return unless current_class.respond_to?'states'
58
+
59
+ node_attribs = []
60
+ node_type = 'aasm'
61
+
62
+ current_class.states.each do |state_name|
63
+ state = current_class.read_inheritable_attribute(:states)[state_name]
64
+ node_shape = (current_class.initial_state === state_name) ? ", peripheries = 2" : ""
65
+ node_attribs << "#{current_class.name.downcase}_#{state_name} [label=#{state_name} #{node_shape}];"
66
+ end
67
+ @graph.add_node [node_type, current_class.name, node_attribs]
68
+
69
+ current_class.read_inheritable_attribute(:transition_table).each do |event_name, event|
70
+ event.each do |transition|
71
+ @graph.add_edge [
72
+ 'event',
73
+ current_class.name.downcase + "_" + transition.from.to_s,
74
+ current_class.name.downcase + "_" + transition.to.to_s,
75
+ event_name.to_s
76
+ ]
77
+ end
78
+ end
79
+ end # process_class
80
+
81
+ end # class AasmDiagram
@@ -1,7 +1,7 @@
1
1
  # RailRoad - RoR diagrams generator
2
2
  # http://railroad.rubyforge.org
3
3
  #
4
- # Copyright 2007 - Javier Smaldone (http://www.smaldone.com.ar)
4
+ # Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
5
5
  # See COPYING for more details
6
6
 
7
7
  require 'railroad/diagram_graph'
@@ -81,7 +81,9 @@ class AppDiagram
81
81
 
82
82
  # Extract class name from filename
83
83
  def extract_class_name(filename)
84
- filename.split('/')[2..-1].join('/').split('.').first.camelize
84
+ #filename.split('/')[2..-1].join('/').split('.').first.camelize
85
+ # Fixed by patch from ticket #12742
86
+ File.basename(filename).chomp(".rb").camelize
85
87
  end
86
88
 
87
89
  end # class AppDiagram
@@ -1,7 +1,7 @@
1
1
  # RailRoad - RoR diagrams generator
2
2
  # http://railroad.rubyforge.org
3
3
  #
4
- # Copyright 2007 - Javier Smaldone (http://www.smaldone.com.ar)
4
+ # Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
5
5
  # See COPYING for more details
6
6
 
7
7
  require 'railroad/app_diagram'
@@ -10,7 +10,7 @@ require 'railroad/app_diagram'
10
10
  class ControllersDiagram < AppDiagram
11
11
 
12
12
  def initialize(options)
13
- options.exclude.map! {|e| "app/controllers/" + e}
13
+ #options.exclude.map! {|e| "app/controllers/" + e}
14
14
  super options
15
15
  @graph.diagram_type = 'Controllers'
16
16
  end
@@ -1,7 +1,7 @@
1
1
  # RailRoad - RoR diagrams generator
2
2
  # http://railroad.rubyforge.org
3
3
  #
4
- # Copyright 2007 - Javier Smaldone (http://www.smaldone.com.ar)
4
+ # Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
5
5
  # See COPYING for more details
6
6
 
7
7
 
@@ -97,6 +97,9 @@ class DiagramGraph
97
97
  options = ''
98
98
  when 'module'
99
99
  options = 'shape=box, style=dotted, label="' + name + '"'
100
+ when 'aasm'
101
+ # Return subgraph format
102
+ return "subgraph cluster_#{name.downcase} {\n\tlabel = #{quote(name)}\n\t#{attributes.join("\n ")}}"
100
103
  end # case
101
104
  return "\t#{quote(name)} [#{options}]\n"
102
105
  end # dot_node
@@ -106,13 +109,18 @@ class DiagramGraph
106
109
  options = name != '' ? "label=\"#{name}\", " : ''
107
110
  case type
108
111
  when 'one-one'
109
- options += 'taillabel="1"'
112
+ #options += 'taillabel="1"'
113
+ options += 'arrowtail=odot, arrowhead=dot, dir=both'
110
114
  when 'one-many'
111
- options += 'taillabel="n"'
115
+ #options += 'taillabel="n"'
116
+ options += 'arrowtail=crow, arrowhead=dot, dir=both'
112
117
  when 'many-many'
113
- options += 'taillabel="n", headlabel="n", arrowtail="normal"'
118
+ #options += 'taillabel="n", headlabel="n", arrowtail="normal"'
119
+ options += 'arrowtail=crow, arrowhead=crow, dir=both'
114
120
  when 'is-a'
115
121
  options += 'arrowhead="none", arrowtail="onormal"'
122
+ when 'event'
123
+ options += "fontsize=10"
116
124
  end
117
125
  return "\t#{quote(from)} -> #{quote(to)} [#{options}]\n"
118
126
  end # dot_edge
@@ -1,7 +1,7 @@
1
1
  # RailRoad - RoR diagrams generator
2
2
  # http://railroad.rubyforge.org
3
3
  #
4
- # Copyright 2007 - Javier Smaldone (http://www.smaldone.com.ar)
4
+ # Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
5
5
  # See COPYING for more details
6
6
 
7
7
  require 'railroad/app_diagram'
@@ -10,7 +10,7 @@ require 'railroad/app_diagram'
10
10
  class ModelsDiagram < AppDiagram
11
11
 
12
12
  def initialize(options)
13
- options.exclude.map! {|e| "app/models/" + e}
13
+ #options.exclude.map! {|e| "app/models/" + e}
14
14
  super options
15
15
  @graph.diagram_type = 'Models'
16
16
  # Processed habtm associations
@@ -20,7 +20,9 @@ class ModelsDiagram < AppDiagram
20
20
  # Process model files
21
21
  def generate
22
22
  STDERR.print "Generating models diagram\n" if @options.verbose
23
- files = Dir.glob("app/models/**/*.rb") - @options.exclude
23
+ files = Dir.glob("app/models/**/*.rb")
24
+ files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
25
+ files -= @options.exclude
24
26
  files.each do |f|
25
27
  process_class extract_class_name(f).constantize
26
28
  end
@@ -32,7 +34,9 @@ class ModelsDiagram < AppDiagram
32
34
  def load_classes
33
35
  begin
34
36
  disable_stdout
35
- files = Dir.glob("app/models/**/*.rb") - @options.exclude
37
+ files = Dir.glob("app/models/**/*.rb")
38
+ files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
39
+ files -= @options.exclude
36
40
  files.each {|m| require m }
37
41
  enable_stdout
38
42
  rescue LoadError
@@ -48,16 +52,36 @@ class ModelsDiagram < AppDiagram
48
52
  STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
49
53
 
50
54
  generated = false
51
-
55
+
52
56
  # Is current_clas derived from ActiveRecord::Base?
53
57
  if current_class.respond_to?'reflect_on_all_associations'
58
+
59
+
54
60
  node_attribs = []
55
61
  if @options.brief || current_class.abstract_class?
56
62
  node_type = 'model-brief'
57
63
  else
58
64
  node_type = 'model'
65
+
59
66
  # Collect model's content columns
60
- current_class.content_columns.each do |a|
67
+
68
+ content_columns = current_class.content_columns
69
+
70
+ if @options.hide_magic
71
+ # From patch #13351
72
+ # http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
73
+ magic_fields = [
74
+ "created_at", "created_on", "updated_at", "updated_on",
75
+ "lock_version", "type", "id", "position", "parent_id", "lft",
76
+ "rgt", "quote", "template"
77
+ ]
78
+ magic_fields << current_class.table_name + "_count" if current_class.respond_to? 'table_name'
79
+ content_columns = current_class.content_columns.select {|c| ! magic_fields.include? c.name}
80
+ else
81
+ content_columns = current_class.content_columns
82
+ end
83
+
84
+ content_columns.each do |a|
61
85
  content_column = a.name
62
86
  content_column += ' :' + a.type.to_s unless @options.hide_types
63
87
  node_attribs << content_column
@@ -104,7 +128,11 @@ class ModelsDiagram < AppDiagram
104
128
  return if assoc.macro.to_s == 'belongs_to'
105
129
 
106
130
  # Only non standard association names needs a label
107
- if assoc.class_name == assoc.name.to_s.singularize.camelize
131
+
132
+ # from patch #12384
133
+ # if assoc.class_name == assoc.name.to_s.singularize.camelize
134
+ assoc_class_name = (assoc.class_name.respond_to? 'underscore') ? assoc.class_name.underscore.singularize.camelize : assoc.class_name
135
+ if assoc_class_name == assoc.name.to_s.singularize.camelize
108
136
  assoc_name = ''
109
137
  else
110
138
  assoc_name = assoc.name.to_s
@@ -119,7 +147,9 @@ class ModelsDiagram < AppDiagram
119
147
  assoc_type = 'many-many'
120
148
  @habtm << [class_name, assoc.class_name, assoc_name]
121
149
  end
122
- @graph.add_edge [assoc_type, class_name, assoc.class_name, assoc_name]
150
+ # from patch #12384
151
+ # @graph.add_edge [assoc_type, class_name, assoc.class_name, assoc_name]
152
+ @graph.add_edge [assoc_type, class_name, assoc_class_name, assoc_name]
123
153
  end # process_association
124
154
 
125
155
  end # class ModelsDiagram
@@ -1,7 +1,7 @@
1
1
  # RailRoad - RoR diagrams generator
2
2
  # http://railroad.rubyforge.org
3
3
  #
4
- # Copyright 2007 - Javier Smaldone (http://www.smaldone.com.ar)
4
+ # Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
5
5
  # See COPYING for more details
6
6
 
7
7
  require 'ostruct'
@@ -19,10 +19,13 @@ class OptionsStruct < OpenStruct
19
19
  :join => false,
20
20
  :label => false,
21
21
  :modules => false,
22
+ :hide_magic => false,
22
23
  :hide_types => false,
23
24
  :hide_public => false,
24
25
  :hide_protected => false,
25
26
  :hide_private => false,
27
+ :plugins_models => false,
28
+ :root => '',
26
29
  :transitive => false,
27
30
  :verbose => false,
28
31
  :xmi => false,
@@ -39,8 +42,7 @@ class OptionsStruct < OpenStruct
39
42
  " (no attributes nor methods)") do |b|
40
43
  self.brief = b
41
44
  end
42
- opts.on("-e", "--exclude file1[,fileN]", Array, "Exclude files",
43
- " (relative path to 'app/models/' or", " 'app/controllers/')") do |list|
45
+ opts.on("-e", "--exclude file1[,fileN]", Array, "Exclude given files") do |list|
44
46
  self.exclude = list
45
47
  end
46
48
  opts.on("-i", "--inheritance", "Include inheritance relations") do |i|
@@ -53,6 +55,9 @@ class OptionsStruct < OpenStruct
53
55
  opts.on("-o", "--output FILE", "Write diagram to file FILE") do |f|
54
56
  self.output = f
55
57
  end
58
+ opts.on("-r", "--root PATH", "Set PATH as the application root") do |r|
59
+ self.root = r
60
+ end
56
61
  opts.on("-v", "--verbose", "Enable verbose output",
57
62
  " (produce messages to STDOUT)") do |v|
58
63
  self.verbose = v
@@ -67,6 +72,9 @@ class OptionsStruct < OpenStruct
67
72
  " (not only ActiveRecord::Base derived)") do |a|
68
73
  self.all = a
69
74
  end
75
+ opts.on("--hide-magic", "Hide magic field names") do |h|
76
+ self.hide_magic = h
77
+ end
70
78
  opts.on("--hide-types", "Hide attributes type") do |h|
71
79
  self.hide_types = h
72
80
  end
@@ -76,6 +84,9 @@ class OptionsStruct < OpenStruct
76
84
  opts.on("-m", "--modules", "Include modules") do |m|
77
85
  self.modules = m
78
86
  end
87
+ opts.on("-p", "--plugins-models", "Include plugins models") do |p|
88
+ self.plugins_models = p
89
+ end
79
90
  opts.on("-t", "--transitive", "Include transitive associations",
80
91
  "(through inheritance)") do |t|
81
92
  self.transitive = t
@@ -106,26 +117,33 @@ class OptionsStruct < OpenStruct
106
117
  opts.separator ""
107
118
  opts.separator "Commands (you must supply one of these):"
108
119
  opts.on("-M", "--models", "Generate models diagram") do |c|
109
- if self.command == 'controllers'
110
- STDERR.print "Error: Can't generate models AND " +
111
- "controllers diagram\n\n"
120
+ if self.command != ''
121
+ STDERR.print "Error: Can only generate one diagram type\n\n"
112
122
  exit 1
113
123
  else
114
124
  self.command = 'models'
115
125
  end
116
126
  end
117
127
  opts.on("-C", "--controllers", "Generate controllers diagram") do |c|
118
- if self.command == 'models'
119
- STDERR.print "Error: Can't generate models AND " +
120
- "controllers diagram\n\n"
128
+ if self.command != ''
129
+ STDERR.print "Error: Can only generate one diagram type\n\n"
121
130
  exit 1
122
131
  else
123
132
  self.command = 'controllers'
124
133
  end
125
134
  end
135
+ # From Ana Nelson's patch
136
+ opts.on("-A", "--aasm", "Generate \"acts as state machine\" diagram") do |c|
137
+ if self.command == 'controllers'
138
+ STDERR.print "Error: Can only generate one diagram type\n\n"
139
+ exit 1
140
+ else
141
+ self.command = 'aasm'
142
+ end
143
+ end
126
144
  opts.separator ""
127
145
  opts.separator "For bug reporting and additional information, please see:"
128
- opts.separator "http://railroad.rubyforge.org"
146
+ opts.separator "http://railroad.rubyforge.org/"
129
147
  end # do
130
148
 
131
149
  begin
@@ -1,10 +1,11 @@
1
1
  require 'rubygems'
2
2
  SPEC = Gem::Specification.new do |s|
3
3
  s.name = "railroad"
4
- s.version = "0.4.1"
4
+ s.version = "0.5.0"
5
5
  s.author = "Javier Smaldone"
6
6
  s.email = "javier@smaldone.com.ar"
7
7
  s.homepage = "http://railroad.rubyforge.org"
8
+ s.rubyforge_project = "railroad"
8
9
  s.platform = Gem::Platform::RUBY
9
10
  s.summary = "A DOT diagram generator for Ruby on Rail applications"
10
11
  s.files = Dir.glob("lib/railroad/*.rb") +
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railroad
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javier Smaldone
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-09 00:00:00 -03:00
12
+ date: 2008-05-10 00:00:00 -03:00
13
13
  default_executable: railroad
14
14
  dependencies: []
15
15
 
@@ -23,6 +23,7 @@ extra_rdoc_files:
23
23
  - README
24
24
  - COPYING
25
25
  files:
26
+ - lib/railroad/aasm_diagram.rb
26
27
  - lib/railroad/models_diagram.rb
27
28
  - lib/railroad/app_diagram.rb
28
29
  - lib/railroad/controllers_diagram.rb
@@ -53,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
54
  version:
54
55
  requirements: []
55
56
 
56
- rubyforge_project:
57
+ rubyforge_project: railroad
57
58
  rubygems_version: 1.1.1
58
59
  signing_key:
59
60
  specification_version: 2