railroady 1.0.6 → 1.0.7

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/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = RailRoady
2
2
 
3
- RailRoady generates Rails 3 model (AcitveRecord, Mongoid) and controller UML diagrams as cross-platform .svg files, as well as in the DOT language.
3
+ RailRoady generates Rails 3 model (AcitveRecord, Mongoid, Datamapper) and controller UML diagrams as cross-platform .svg files, as well as in the DOT language.
4
4
 
5
5
  Code is based on the original "railroad" gem, patched and maintained over the years. Lineage can be traced via GitHub.
6
6
 
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 1
3
3
  :minor: 0
4
- :patch: 6
4
+ :patch: 7
5
5
  :build:
@@ -26,7 +26,7 @@ class ModelsDiagram < AppDiagram
26
26
  end
27
27
 
28
28
  end
29
- end
29
+ end
30
30
 
31
31
  def get_files(prefix ='')
32
32
  files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix << "app/models/**/*.rb")
@@ -38,34 +38,37 @@ class ModelsDiagram < AppDiagram
38
38
  # Process a model class
39
39
  def process_class(current_class)
40
40
  STDERR.puts "Processing #{current_class}" if @options.verbose
41
-
42
- generated = if defined?(Mongoid::Document) && current_class.new.is_a?(Mongoid::Document)
43
- process_mongoid_model(current_class)
44
- elsif current_class.respond_to?'reflect_on_all_associations'
45
- process_active_record_model(current_class)
46
- elsif @options.all && (current_class.is_a? Class)
47
- process_basic_class(current_class)
48
- elsif @options.modules && (current_class.is_a? Module)
49
- process_basic_module(current_class)
50
- end
41
+
42
+ generated =
43
+ if defined?(Mongoid::Document) && current_class.new.is_a?(Mongoid::Document)
44
+ process_mongoid_model(current_class)
45
+ elsif defined?(DataMapper::Resource) && current_class.new.is_a?(DataMapper::Resource)
46
+ process_datamapper_model(current_class)
47
+ elsif current_class.respond_to?'reflect_on_all_associations'
48
+ process_active_record_model(current_class)
49
+ elsif @options.all && (current_class.is_a? Class)
50
+ process_basic_class(current_class)
51
+ elsif @options.modules && (current_class.is_a? Module)
52
+ process_basic_module(current_class)
53
+ end
51
54
 
52
55
  if @options.inheritance && generated && include_inheritance?(current_class)
53
56
  @graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
54
- end
55
-
57
+ end
58
+
56
59
  end # process_class
57
-
60
+
58
61
  def include_inheritance?(current_class)
59
62
  (defined?(ActiveRecord::Base) && current_class.superclass != ActiveRecord::Base) &&
60
63
  (current_class.superclass != Object)
61
64
  end
62
-
65
+
63
66
  def process_basic_class(current_class)
64
67
  node_type = @options.brief ? 'class-brief' : 'class'
65
68
  @graph.add_node [node_type, current_class.name]
66
69
  true
67
70
  end
68
-
71
+
69
72
  def process_basic_module(current_class)
70
73
  @graph.add_node ['module', current_class.name]
71
74
  false
@@ -86,15 +89,15 @@ class ModelsDiagram < AppDiagram
86
89
  # http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
87
90
  magic_fields = [
88
91
  "created_at", "created_on", "updated_at", "updated_on",
89
- "lock_version", "type", "id", "position", "parent_id", "lft",
92
+ "lock_version", "type", "id", "position", "parent_id", "lft",
90
93
  "rgt", "quote", "template"
91
94
  ]
92
- magic_fields << current_class.table_name + "_count" if current_class.respond_to? 'table_name'
95
+ magic_fields << current_class.table_name + "_count" if current_class.respond_to? 'table_name'
93
96
  content_columns = current_class.content_columns.select {|c| ! magic_fields.include? c.name}
94
97
  else
95
98
  content_columns = current_class.content_columns
96
99
  end
97
-
100
+
98
101
  content_columns.each do |a|
99
102
  content_column = a.name
100
103
  content_column += ' :' + a.type.to_s unless @options.hide_types
@@ -102,27 +105,69 @@ class ModelsDiagram < AppDiagram
102
105
  end
103
106
  end
104
107
  @graph.add_node [node_type, current_class.name, node_attribs]
105
-
108
+
106
109
  # Process class associations
107
110
  associations = current_class.reflect_on_all_associations
108
111
  if @options.inheritance && ! @options.transitive
109
112
  superclass_associations = current_class.superclass.reflect_on_all_associations
110
-
111
- associations = associations.select{|a| ! superclass_associations.include? a}
113
+
114
+ associations = associations.select{|a| ! superclass_associations.include? a}
112
115
  # This doesn't works!
113
116
  # associations -= current_class.superclass.reflect_on_all_associations
114
117
  end
115
-
118
+
116
119
  associations.each do |a|
117
120
  process_association current_class.name, a
118
121
  end
119
-
122
+
120
123
  true
121
124
  end
122
-
125
+
126
+ def process_datamapper_model(current_class)
127
+ node_attribs = []
128
+ if @options.brief #|| current_class.abstract_class?
129
+ node_type = 'model-brief'
130
+ else
131
+ node_type = 'model'
132
+
133
+ # Collect model's properties
134
+ props = current_class.properties.sort_by(&:name)
135
+
136
+ if @options.hide_magic
137
+ # From patch #13351
138
+ # http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
139
+ magic_fields =
140
+ ["created_at", "created_on", "updated_at", "updated_on", "lock_version", "_type", "_id",
141
+ "position", "parent_id", "lft", "rgt", "quote", "template"]
142
+ props = props.select {|c| !magic_fields.include?(c.name.to_s) }
143
+ end
144
+
145
+ props.each do |a|
146
+ prop = a.name.to_s
147
+ prop += ' :' + a.class.name.split('::').last unless @options.hide_types
148
+ node_attribs << prop
149
+ end
150
+ end
151
+ @graph.add_node [node_type, current_class.name, node_attribs]
152
+
153
+ # Process relationships
154
+ relationships = current_class.relationships
155
+
156
+ # TODO: Manage inheritance
157
+
158
+ relationships.each do |a|
159
+ process_datamapper_relationship current_class.name, a
160
+ end
161
+
162
+ true
163
+ end
164
+
165
+
166
+
167
+
123
168
  def process_mongoid_model(current_class)
124
169
  node_attribs = []
125
-
170
+
126
171
  if @options.brief
127
172
  node_type = 'model-brief'
128
173
  else
@@ -141,31 +186,31 @@ class ModelsDiagram < AppDiagram
141
186
  ]
142
187
  content_columns = content_columns.select {|c| !magic_fields.include?(c.name) }
143
188
  end
144
-
189
+
145
190
  content_columns.each do |a|
146
191
  content_column = a.name
147
192
  content_column += " :#{a.type}" unless @options.hide_types
148
193
  node_attribs << content_column
149
194
  end
150
195
  end
151
-
196
+
152
197
  @graph.add_node [node_type, current_class.name, node_attribs]
153
-
198
+
154
199
  # Process class associations
155
200
  associations = current_class.relations.values
156
-
201
+
157
202
  if @options.inheritance && !@options.transitive &&
158
203
  current_class.superclass.respond_to?(:relations)
159
204
  associations -= current_class.superclass.relations.values
160
205
  end
161
-
206
+
162
207
  associations.each do |a|
163
208
  process_association current_class.name, a
164
209
  end
165
-
210
+
166
211
  true
167
212
  end
168
-
213
+
169
214
 
170
215
  # Process a model association
171
216
  def process_association(class_name, assoc)
@@ -175,21 +220,21 @@ class ModelsDiagram < AppDiagram
175
220
  macro = assoc.macro.to_s
176
221
  return if %w[belongs_to referenced_in].include?(macro) && !@options.show_belongs_to
177
222
 
178
- #TODO:
223
+ #TODO:
179
224
  # FAIL: assoc.methods.include?(:class_name)
180
225
  # FAIL: assoc.responds_to?(:class_name)
181
226
  assoc_class_name = assoc.class_name rescue nil
182
227
  assoc_class_name ||= assoc.name.to_s.underscore.singularize.camelize
183
-
228
+
184
229
  # Only non standard association names needs a label
185
-
230
+
186
231
  # from patch #12384
187
232
  # if assoc.class_name == assoc.name.to_s.singularize.camelize
188
233
  if assoc_class_name == assoc.name.to_s.singularize.camelize
189
234
  assoc_name = ''
190
235
  else
191
236
  assoc_name = assoc.name.to_s
192
- end
237
+ end
193
238
 
194
239
  # Patch from "alpack" to support classes in a non-root module namespace. See: http://disq.us/yxl1v
195
240
  if class_name.include?("::") && !assoc_class_name.include?("::")
@@ -207,9 +252,45 @@ class ModelsDiagram < AppDiagram
207
252
  return if @habtm.include? [assoc_class_name, class_name, assoc_name]
208
253
  assoc_type = 'many-many'
209
254
  @habtm << [class_name, assoc_class_name, assoc_name]
210
- end
211
- # from patch #12384
255
+ end
256
+ # from patch #12384
212
257
  # @graph.add_edge [assoc_type, class_name, assoc.class_name, assoc_name]
213
- @graph.add_edge [assoc_type, class_name, assoc_class_name, assoc_name]
258
+ @graph.add_edge [assoc_type, class_name, assoc_class_name, assoc_name]
214
259
  end # process_association
215
260
  end # class ModelsDiagram
261
+
262
+ # Process a DataMapper relationship
263
+ def process_datamapper_relationship(class_name, relation)
264
+ STDERR.puts "- Processing DataMapper model relationship #{relation.name.to_s}" if @options.verbose
265
+
266
+ # Skip "belongs_to" relationships
267
+ dm_type = relation.class.to_s.split('::')[-2]
268
+ return if dm_type == 'ManyToOne' && !@options.show_belongs_to
269
+
270
+ dm_parent_model = relation.parent_model.to_s
271
+ dm_child_model = relation.child_model.to_s
272
+
273
+ assoc_class_name = ''
274
+ # Get the assoc_class_name
275
+ if dm_parent_model.eql?(class_name)
276
+ assoc_class_name = dm_child_model
277
+ else
278
+ assoc_class_name = dm_parent_model
279
+ end
280
+
281
+ # Only non standard association names needs a label
282
+ assoc_name = ''
283
+ if !(relation.name.to_s.singularize.camelize.eql?(assoc_class_name.split('::').last))
284
+ assoc_name = relation.name.to_s
285
+ end
286
+
287
+ # TO BE IMPROVED
288
+ rel_type = 'many-many' # default value for ManyToOne and ManyToMany
289
+ if dm_type == 'OneToOne'
290
+ rel_type = 'one-one'
291
+ elsif dm_type == 'OneToMany'
292
+ rel_type = 'one-many'
293
+ end
294
+
295
+ @graph.add_edge [rel_type, class_name, assoc_class_name, assoc_name ]
296
+ end
data/tasks/railroady.rake CHANGED
@@ -7,22 +7,27 @@
7
7
  #
8
8
  # Author: Preston Lee, http://railroady.prestonlee.com
9
9
 
10
- # Returns an absolute path for the following file.
11
- def format
12
- @@DIAGRAM_FORMAT ||= 'svg'
13
- end
10
+ # wrap helper methods so they don't conflict w/ methods on Object
11
+ module RailRoady
12
+ class RakeHelpers
13
+ def self.format
14
+ @@DIAGRAM_FORMAT ||= 'svg'
15
+ end
14
16
 
15
- def full_path(name = 'test.txt')
16
- f = File.join(Rails.root.to_s.gsub(' ', '\ '), 'doc', name)
17
- f.to_s
17
+ # Returns an absolute path for the following file.
18
+ def self.full_path(name = 'test.txt')
19
+ f = File.join(Rails.root.to_s.gsub(' ', '\ '), 'doc', name)
20
+ f.to_s
21
+ end
22
+ end
18
23
  end
19
24
 
20
25
  namespace :diagram do
21
26
 
22
- @MODELS_ALL = full_path("models_complete.#{format}").freeze
23
- @MODELS_BRIEF = full_path("models_brief.#{format}").freeze
24
- @CONTROLLERS_ALL = full_path("controllers_complete.#{format}").freeze
25
- @CONTROLLERS_BRIEF = full_path("controllers_brief.#{format}").freeze
27
+ @MODELS_ALL = RailRoady::RakeHelpers.full_path("models_complete.#{RailRoady::RakeHelpers.format}").freeze
28
+ @MODELS_BRIEF = RailRoady::RakeHelpers.full_path("models_brief.#{RailRoady::RakeHelpers.format}").freeze
29
+ @CONTROLLERS_ALL = RailRoady::RakeHelpers.full_path("controllers_complete.#{RailRoady::RakeHelpers.format}").freeze
30
+ @CONTROLLERS_BRIEF = RailRoady::RakeHelpers.full_path("controllers_brief.#{RailRoady::RakeHelpers.format}").freeze
26
31
 
27
32
  namespace :models do
28
33
 
@@ -30,14 +35,14 @@ namespace :diagram do
30
35
  task :complete do
31
36
  f = @MODELS_ALL
32
37
  puts "Generating #{f}"
33
- sh "railroady -ilamM | dot -T#{format} > #{f}"
38
+ sh "railroady -ilamM | dot -T#{RailRoady::RakeHelpers.format} > #{f}"
34
39
  end
35
40
 
36
41
  desc 'Generates an abbreviated class diagram for all models.'
37
42
  task :brief do
38
43
  f = @MODELS_BRIEF
39
44
  puts "Generating #{f}"
40
- sh "railroady -bilamM | dot -T#{format} > #{f}"
45
+ sh "railroady -bilamM | dot -T#{RailRoady::RakeHelpers.format} > #{f}"
41
46
  end
42
47
 
43
48
  end
@@ -48,14 +53,14 @@ namespace :diagram do
48
53
  task :complete do
49
54
  f = @CONTROLLERS_ALL
50
55
  puts "Generating #{f}"
51
- sh "railroady -ilC | neato -T#{format} > #{f}"
56
+ sh "railroady -ilC | neato -T#{RailRoady::RakeHelpers.format} > #{f}"
52
57
  end
53
58
 
54
59
  desc 'Generates an abbreviated class diagram for all controllers.'
55
60
  task :brief do
56
61
  f = @CONTROLLERS_BRIEF
57
62
  puts "Generating #{f}"
58
- sh "railroady -bilC | neato -T#{format} > #{f}"
63
+ sh "railroady -bilC | neato -T#{RailRoady::RakeHelpers.format} > #{f}"
59
64
  end
60
65
 
61
66
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railroady
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 6
10
- version: 1.0.6
9
+ - 7
10
+ version: 1.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Preston Lee
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2012-02-03 00:00:00 +05:30
21
+ date: 2012-02-28 00:00:00 +05:30
22
22
  default_executable: railroady
23
23
  dependencies: []
24
24