prailroady 1.5.3 → 1.6.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/AUTHORS.rdoc +1 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +13 -13
- data/README.md +4 -0
- data/bin/prailroady +4 -2
- data/lib/prailroady/aasm_diagram.rb +15 -39
- data/lib/prailroady/app_diagram.rb +16 -16
- data/lib/prailroady/controllers_diagram.rb +23 -17
- data/lib/prailroady/models_diagram.rb +39 -35
- data/lib/prailroady/options_struct.rb +12 -11
- data/lib/prailroady/version.rb +2 -1
- data/lib/prailroady.rb +10 -2
- data/prailroady.gemspec +1 -0
- metadata +6 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: db58ff716ee21346c67b6382fbcd48eb30667aca10de1f44ca684b722515270a
|
|
4
|
+
data.tar.gz: 21becfea99d5810f2824beed8a44e0ac433fc25c70302aa2ff88d280e184257d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6fee736b23e129288f01fd765b1fd7518f34802d0b58373a8927b7a95ea63dc49d90a61d444e89339c266d2f9284fc8ed4a6a88f4d041cc442e894f07f1cf9a8
|
|
7
|
+
data.tar.gz: 8816a14be17885d1820f4e515a45998301e3c90e167b8df2927b47ac32d57952d214af6c064d8e613570fd08253c115e2f7aef9bec3a1e90154ca208cf2c3fca
|
data/.travis.yml
CHANGED
data/AUTHORS.rdoc
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -6,21 +6,21 @@ PATH
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
-
activesupport (
|
|
9
|
+
activesupport (7.0.2.3)
|
|
10
10
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
11
|
-
i18n (
|
|
12
|
-
minitest (
|
|
13
|
-
tzinfo (~>
|
|
14
|
-
concurrent-ruby (1.
|
|
15
|
-
i18n (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
tzinfo (
|
|
20
|
-
|
|
11
|
+
i18n (>= 1.6, < 2)
|
|
12
|
+
minitest (>= 5.1)
|
|
13
|
+
tzinfo (~> 2.0)
|
|
14
|
+
concurrent-ruby (1.1.10)
|
|
15
|
+
i18n (1.10.0)
|
|
16
|
+
concurrent-ruby (~> 1.0)
|
|
17
|
+
minitest (5.15.0)
|
|
18
|
+
rake (13.0.6)
|
|
19
|
+
tzinfo (2.0.4)
|
|
20
|
+
concurrent-ruby (~> 1.0)
|
|
21
21
|
|
|
22
22
|
PLATFORMS
|
|
23
|
-
|
|
23
|
+
arm64-darwin-21
|
|
24
24
|
|
|
25
25
|
DEPENDENCIES
|
|
26
26
|
activesupport
|
|
@@ -30,4 +30,4 @@ DEPENDENCIES
|
|
|
30
30
|
rake
|
|
31
31
|
|
|
32
32
|
BUNDLED WITH
|
|
33
|
-
|
|
33
|
+
2.2.31
|
data/README.md
CHANGED
data/bin/prailroady
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
# PrailRoady - RoR diagrams generator
|
|
4
5
|
# http://github.com/preston/railroady
|
|
@@ -25,7 +26,8 @@ APP_HUMAN_NAME = 'PrailRoady'
|
|
|
25
26
|
APP_VERSION = PrailRoady::VERSION
|
|
26
27
|
COPYRIGHT = 'Copyright (C) 2007-2008 Javier Smaldone, 2009 Peter Hoeg, 2010-2015 Preston Lee'
|
|
27
28
|
|
|
28
|
-
options = OptionsStruct.new(app_name: APP_NAME, app_human_name: APP_HUMAN_NAME, app_version: APP_VERSION,
|
|
29
|
+
options = OptionsStruct.new(app_name: APP_NAME, app_human_name: APP_HUMAN_NAME, app_version: APP_VERSION,
|
|
30
|
+
copyright: COPYRIGHT)
|
|
29
31
|
|
|
30
32
|
options.parse ARGV
|
|
31
33
|
|
|
@@ -44,7 +46,7 @@ when 'controllers'
|
|
|
44
46
|
when 'aasm'
|
|
45
47
|
diagram = AasmDiagram.new(options)
|
|
46
48
|
else
|
|
47
|
-
|
|
49
|
+
$stderr.print "#{APP_HUMAN_NAME} v#{APP_VERSION}\n" \
|
|
48
50
|
"Error: You must supply a command\n" \
|
|
49
51
|
" (try #{APP_NAME} -h)\n\n"
|
|
50
52
|
exit 1
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
# PrailRoady - RoR diagrams generator
|
|
2
3
|
# http://railroad.rubyforge.org
|
|
3
4
|
#
|
|
@@ -20,18 +21,17 @@ class AasmDiagram < AppDiagram
|
|
|
20
21
|
|
|
21
22
|
# Process model files
|
|
22
23
|
def generate
|
|
23
|
-
|
|
24
|
+
$stderr.print "Generating AASM diagram\n" if @options.verbose
|
|
24
25
|
get_files.each do |f|
|
|
25
26
|
process_class extract_class_name(f).constantize
|
|
26
27
|
end
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def get_files(prefix = '')
|
|
30
|
-
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix
|
|
31
|
+
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob("#{prefix}app/models/**/*.rb")
|
|
31
32
|
files += Dir.glob('vendor/plugins/**/app/models/*.rb') if @options.plugins_models
|
|
32
|
-
files
|
|
33
|
-
|
|
34
|
-
files
|
|
33
|
+
files - Dir.glob("#{prefix}app/models/concerns/**/*.rb") unless @options.include_concerns
|
|
34
|
+
Dir.glob(@options.exclude)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
private
|
|
@@ -45,49 +45,25 @@ class AasmDiagram < AppDiagram
|
|
|
45
45
|
enable_stdout
|
|
46
46
|
print_error 'model classes'
|
|
47
47
|
raise
|
|
48
|
-
end
|
|
48
|
+
end
|
|
49
49
|
|
|
50
50
|
# Process a model class
|
|
51
51
|
def process_class(current_class)
|
|
52
|
-
|
|
52
|
+
$stderr.print "\tProcessing #{current_class}\n" if @options.verbose
|
|
53
53
|
|
|
54
|
-
# Only interested in
|
|
55
|
-
process_acts_as_state_machine_class(current_class) if current_class.respond_to?(:states)
|
|
54
|
+
# Only interested in aasm models.
|
|
56
55
|
process_aasm_class(current_class) if current_class.respond_to?(:aasm_states) || current_class.respond_to?(:aasm)
|
|
57
|
-
end # process_class
|
|
58
|
-
|
|
59
|
-
def process_acts_as_state_machine_class(current_class)
|
|
60
|
-
node_attribs = []
|
|
61
|
-
node_type = 'aasm'
|
|
62
|
-
|
|
63
|
-
STDERR.print "\t\tprocessing as acts_as_state_machine\n" if @options.verbose
|
|
64
|
-
current_class.aasm.states.each do |state_name|
|
|
65
|
-
node_shape = (current_class.aasm.initial_state == state_name) ? ', peripheries = 2' : ''
|
|
66
|
-
node_attribs << "#{current_class.name.downcase}_#{state_name} [label=#{state_name} #{node_shape}];"
|
|
67
|
-
end
|
|
68
|
-
@graph.add_node [node_type, current_class.name, node_attribs]
|
|
69
|
-
|
|
70
|
-
current_class.aasm.events.each do |event|
|
|
71
|
-
event_name = event.name
|
|
72
|
-
event.transitions.each do |transition|
|
|
73
|
-
@graph.add_edge [
|
|
74
|
-
'event',
|
|
75
|
-
current_class.name.downcase + '_' + transition.from.to_s,
|
|
76
|
-
current_class.name.downcase + '_' + transition.to.to_s,
|
|
77
|
-
event_name.to_s
|
|
78
|
-
]
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
56
|
end
|
|
82
57
|
|
|
83
58
|
def process_aasm_class(current_class)
|
|
84
59
|
node_attribs = []
|
|
85
60
|
node_type = 'aasm'
|
|
61
|
+
diagram_friendly_class_name = current_class.name.downcase.gsub(/[^a-z0-9\-_]+/i, '_')
|
|
86
62
|
|
|
87
|
-
|
|
63
|
+
$stderr.print "\t\tprocessing as aasm\n" if @options.verbose
|
|
88
64
|
current_class.aasm.states.each do |state|
|
|
89
|
-
node_shape =
|
|
90
|
-
node_attribs << "#{
|
|
65
|
+
node_shape = current_class.aasm.initial_state == state.name ? ', peripheries = 2' : ''
|
|
66
|
+
node_attribs << "#{diagram_friendly_class_name}_#{state.name} [label=#{state.name} #{node_shape}];"
|
|
91
67
|
end
|
|
92
68
|
@graph.add_node [node_type, current_class.name, node_attribs]
|
|
93
69
|
|
|
@@ -95,11 +71,11 @@ class AasmDiagram < AppDiagram
|
|
|
95
71
|
event.transitions.each do |transition|
|
|
96
72
|
@graph.add_edge [
|
|
97
73
|
'event',
|
|
98
|
-
|
|
99
|
-
|
|
74
|
+
"#{diagram_friendly_class_name}_#{transition.from}",
|
|
75
|
+
"#{diagram_friendly_class_name}_#{transition.to}",
|
|
100
76
|
event.name.to_s
|
|
101
77
|
]
|
|
102
78
|
end
|
|
103
79
|
end
|
|
104
80
|
end
|
|
105
|
-
end
|
|
81
|
+
end
|
|
@@ -18,25 +18,25 @@ class AppDiagram
|
|
|
18
18
|
# Print diagram
|
|
19
19
|
def print
|
|
20
20
|
if @options.output
|
|
21
|
-
old_stdout =
|
|
21
|
+
old_stdout = $stdout.dup
|
|
22
22
|
begin
|
|
23
|
-
|
|
23
|
+
$stdout.reopen(@options.output)
|
|
24
24
|
rescue
|
|
25
|
-
|
|
25
|
+
$stderr.print "Error: Cannot write diagram to #{@options.output}\n\n"
|
|
26
26
|
exit 2
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
if @options.xmi
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
$stderr.print "Generating XMI diagram\n" if @options.verbose
|
|
32
|
+
$stdout.print @graph.to_xmi
|
|
33
33
|
else
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
$stderr.print "Generating DOT graph\n" if @options.verbose
|
|
35
|
+
$stdout.print @graph.to_dot
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
end
|
|
38
|
+
$stdout.reopen(old_stdout) if @options.output
|
|
39
|
+
end
|
|
40
40
|
|
|
41
41
|
def process
|
|
42
42
|
load_environment
|
|
@@ -61,7 +61,7 @@ class AppDiagram
|
|
|
61
61
|
|
|
62
62
|
# Load Rails application's environment
|
|
63
63
|
def load_environment
|
|
64
|
-
|
|
64
|
+
$stderr.print "Loading application environment\n" if @options.verbose
|
|
65
65
|
begin
|
|
66
66
|
disable_stdout
|
|
67
67
|
l = File.join(Dir.pwd.to_s, @options.config_file)
|
|
@@ -72,24 +72,24 @@ class AppDiagram
|
|
|
72
72
|
print_error 'application environment'
|
|
73
73
|
raise
|
|
74
74
|
end
|
|
75
|
-
|
|
75
|
+
$stderr.print "Loading application classes as we go\n" if @options.verbose
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Prevents Rails application from writing to STDOUT
|
|
79
79
|
def disable_stdout
|
|
80
|
-
@old_stdout =
|
|
80
|
+
@old_stdout = $stdout.dup
|
|
81
81
|
# via Tomas Matousek, http://www.ruby-forum.com/topic/205887
|
|
82
|
-
|
|
82
|
+
$stdout.reopen(::RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw/ ? 'NUL' : '/dev/null')
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
# Restore STDOUT
|
|
86
86
|
def enable_stdout
|
|
87
|
-
|
|
87
|
+
$stdout.reopen(@old_stdout)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
# Print error when loading Rails application
|
|
91
91
|
def print_error(type)
|
|
92
|
-
|
|
92
|
+
$stderr.print "Error loading #{type}.\n (Are you running " \
|
|
93
93
|
"#{@options.app_name} on the application's root directory?)\n\n"
|
|
94
94
|
end
|
|
95
95
|
|
|
@@ -100,4 +100,4 @@ class AppDiagram
|
|
|
100
100
|
# File.basename(filename).chomp(".rb").camelize
|
|
101
101
|
filename.split('/')[2..-1].collect(&:camelize).join('::').chomp('.rb')
|
|
102
102
|
end
|
|
103
|
-
end
|
|
103
|
+
end
|
|
@@ -20,7 +20,7 @@ class ControllersDiagram < AppDiagram
|
|
|
20
20
|
|
|
21
21
|
# Process controller files
|
|
22
22
|
def generate
|
|
23
|
-
|
|
23
|
+
$stderr.print "Generating controllers diagram\n" if @options.verbose
|
|
24
24
|
files = get_files
|
|
25
25
|
# only add APP_CONTROLLER if it isn't already included from the glob above
|
|
26
26
|
files << APP_CONTROLLER unless files.include? APP_CONTROLLER
|
|
@@ -31,10 +31,10 @@ class ControllersDiagram < AppDiagram
|
|
|
31
31
|
begin
|
|
32
32
|
process_class class_name.constantize
|
|
33
33
|
rescue Exception
|
|
34
|
-
|
|
34
|
+
$stderr.print "Warning: exception #{$ERROR_INFO} raised while trying to load controller class #{f}"
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
|
-
end
|
|
37
|
+
end
|
|
38
38
|
|
|
39
39
|
def get_files(prefix = '')
|
|
40
40
|
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix << 'app/controllers/**/*_controller.rb')
|
|
@@ -48,7 +48,7 @@ class ControllersDiagram < AppDiagram
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def extract_class_name(filename)
|
|
51
|
-
filename.match(
|
|
51
|
+
filename.match(%r{.*/controllers/(.*).rb$})[1].camelize
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
private
|
|
@@ -64,11 +64,11 @@ class ControllersDiagram < AppDiagram
|
|
|
64
64
|
enable_stdout
|
|
65
65
|
print_error 'controller classes'
|
|
66
66
|
raise
|
|
67
|
-
end
|
|
67
|
+
end
|
|
68
68
|
|
|
69
69
|
# Proccess a controller class
|
|
70
70
|
def process_class(current_class)
|
|
71
|
-
|
|
71
|
+
$stderr.print "\tProcessing #{current_class}\n" if @options.verbose
|
|
72
72
|
|
|
73
73
|
if @options.brief
|
|
74
74
|
@graph.add_node ['controller-brief', current_class.name]
|
|
@@ -77,15 +77,21 @@ class ControllersDiagram < AppDiagram
|
|
|
77
77
|
node_attribs = { public: [],
|
|
78
78
|
protected: [],
|
|
79
79
|
private: [] }
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
80
|
+
unless @options.hide_public
|
|
81
|
+
current_class.public_instance_methods(false).sort.each do |m|
|
|
82
|
+
node_attribs[:public] << m
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
unless @options.hide_protected
|
|
86
|
+
current_class.protected_instance_methods(false).sort.each do |m|
|
|
87
|
+
node_attribs[:protected] << m
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
unless @options.hide_private
|
|
91
|
+
current_class.private_instance_methods(false).sort.each do |m|
|
|
92
|
+
node_attribs[:private] << m
|
|
93
|
+
end
|
|
94
|
+
end
|
|
89
95
|
@graph.add_node ['controller', current_class.name, node_attribs]
|
|
90
96
|
elsif @options.modules && current_class.is_a?(Module)
|
|
91
97
|
@graph.add_node ['module', current_class.name]
|
|
@@ -95,9 +101,9 @@ class ControllersDiagram < AppDiagram
|
|
|
95
101
|
if @options.inheritance && (transitive_subclasses_of(ApplicationController).include? current_class)
|
|
96
102
|
@graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
|
|
97
103
|
end
|
|
98
|
-
end
|
|
104
|
+
end
|
|
99
105
|
|
|
100
106
|
def transitive_subclasses_of(klass)
|
|
101
107
|
klass.subclasses | klass.subclasses.map { |subklass| transitive_subclasses_of(subklass) }.flatten
|
|
102
108
|
end
|
|
103
|
-
end
|
|
109
|
+
end
|
|
@@ -17,20 +17,20 @@ class ModelsDiagram < AppDiagram
|
|
|
17
17
|
|
|
18
18
|
# Process model files
|
|
19
19
|
def generate
|
|
20
|
-
|
|
20
|
+
warn 'Generating models diagram' if @options.verbose
|
|
21
21
|
get_files.each do |f|
|
|
22
22
|
begin
|
|
23
23
|
process_class extract_class_name(f).constantize
|
|
24
|
-
rescue
|
|
25
|
-
|
|
24
|
+
rescue NoMethodError
|
|
25
|
+
warn "Warning: exception #{$ERROR_INFO} raised while trying to load model class #{f}"
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def get_files(prefix = '')
|
|
31
|
-
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix
|
|
31
|
+
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob("#{prefix}app/models/**/*.rb")
|
|
32
32
|
files += Dir.glob('vendor/plugins/**/app/models/*.rb') if @options.plugins_models
|
|
33
|
-
files -= Dir.glob(prefix
|
|
33
|
+
files -= Dir.glob("#{prefix}app/models/concerns/**/*.rb") unless @options.include_concerns
|
|
34
34
|
files += engine_files if @options.engine_models
|
|
35
35
|
files -= Dir.glob(@options.exclude)
|
|
36
36
|
files
|
|
@@ -41,17 +41,19 @@ class ModelsDiagram < AppDiagram
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def extract_class_name(filename)
|
|
44
|
-
filename_was
|
|
44
|
+
filename_was = filename
|
|
45
|
+
class_name = nil
|
|
45
46
|
|
|
46
47
|
filename = "app/models/#{filename.split('app/models')[1]}"
|
|
47
48
|
|
|
48
49
|
while filename.split('/').length > 2
|
|
49
50
|
begin
|
|
50
|
-
class_name = filename.match(
|
|
51
|
+
class_name = filename.match(%r{.*/models/(.*).rb$})[1]
|
|
52
|
+
class_name = class_name.camelize
|
|
53
|
+
# class_name = class_name.from 2 if class_name.start_with? '::'
|
|
51
54
|
class_name.constantize
|
|
52
|
-
|
|
53
55
|
break
|
|
54
|
-
rescue
|
|
56
|
+
rescue NoMethodError
|
|
55
57
|
class_name = nil
|
|
56
58
|
filename_end = filename.split('/')[2..-1]
|
|
57
59
|
filename_end.shift
|
|
@@ -60,15 +62,16 @@ class ModelsDiagram < AppDiagram
|
|
|
60
62
|
end
|
|
61
63
|
|
|
62
64
|
if class_name.nil?
|
|
63
|
-
filename_was.match(
|
|
65
|
+
filename_was.match(%r{.*/models/(.*).rb$})[1].camelize
|
|
64
66
|
else
|
|
67
|
+
warn class_name
|
|
65
68
|
class_name
|
|
66
69
|
end
|
|
67
70
|
end
|
|
68
71
|
|
|
69
72
|
# Process a model class
|
|
70
73
|
def process_class(current_class)
|
|
71
|
-
|
|
74
|
+
warn "Processing #{current_class}" if @options.verbose
|
|
72
75
|
|
|
73
76
|
generated =
|
|
74
77
|
if defined?(CouchRest::Model::Base) && current_class.new.is_a?(CouchRest::Model::Base)
|
|
@@ -85,13 +88,14 @@ class ModelsDiagram < AppDiagram
|
|
|
85
88
|
process_basic_module(current_class)
|
|
86
89
|
end
|
|
87
90
|
|
|
91
|
+
warn generated
|
|
88
92
|
if @options.inheritance && generated && include_inheritance?(current_class)
|
|
89
93
|
@graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
|
|
90
94
|
end
|
|
91
|
-
end
|
|
95
|
+
end
|
|
92
96
|
|
|
93
97
|
def include_inheritance?(current_class)
|
|
94
|
-
|
|
98
|
+
warn current_class.superclass if @options.verbose
|
|
95
99
|
(defined?(ActiveRecord::Base) ? current_class.superclass != ActiveRecord::Base : true) &&
|
|
96
100
|
(defined?(CouchRest::Model::Base) ? current_class.superclass != CouchRest::Model::Base : true) &&
|
|
97
101
|
(current_class.superclass != Object)
|
|
@@ -121,16 +125,16 @@ class ModelsDiagram < AppDiagram
|
|
|
121
125
|
if @options.hide_magic
|
|
122
126
|
# From patch #13351
|
|
123
127
|
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
|
124
|
-
magic_fields = %w
|
|
125
|
-
magic_fields << current_class.table_name
|
|
126
|
-
content_columns = current_class.content_columns.
|
|
128
|
+
magic_fields = %w[created_at created_on updated_at updated_on lock_version type id position parent_id lft rgt quote template]
|
|
129
|
+
magic_fields << "#{current_class.table_name}_count" if current_class.respond_to? 'table_name'
|
|
130
|
+
content_columns = current_class.content_columns.reject { |c| magic_fields.include? c.name }
|
|
127
131
|
else
|
|
128
132
|
content_columns = current_class.columns
|
|
129
133
|
end
|
|
130
134
|
|
|
131
135
|
content_columns.each do |a|
|
|
132
136
|
content_column = a.name
|
|
133
|
-
content_column +=
|
|
137
|
+
content_column += " :#{a.sql_type.to_s}" unless @options.hide_types
|
|
134
138
|
node_attribs << content_column
|
|
135
139
|
end
|
|
136
140
|
end
|
|
@@ -141,7 +145,7 @@ class ModelsDiagram < AppDiagram
|
|
|
141
145
|
if @options.inheritance && ! @options.transitive
|
|
142
146
|
superclass_associations = current_class.superclass.reflect_on_all_associations
|
|
143
147
|
|
|
144
|
-
associations = associations.
|
|
148
|
+
associations = associations.reject { |a| superclass_associations.include? a }
|
|
145
149
|
# This doesn't works!
|
|
146
150
|
# associations -= current_class.superclass.reflect_on_all_associations
|
|
147
151
|
end
|
|
@@ -167,13 +171,13 @@ class ModelsDiagram < AppDiagram
|
|
|
167
171
|
# From patch #13351
|
|
168
172
|
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
|
169
173
|
magic_fields =
|
|
170
|
-
%w
|
|
171
|
-
props = props.
|
|
174
|
+
%w[created_at created_on updated_at updated_on lock_version _type _id position parent_id lft rgt quote template]
|
|
175
|
+
props = props.reject { |c| magic_fields.include?(c.name.to_s) }
|
|
172
176
|
end
|
|
173
177
|
|
|
174
178
|
props.each do |a|
|
|
175
179
|
prop = a.name.to_s
|
|
176
|
-
prop +=
|
|
180
|
+
prop += " :#{a.class.name.split('::').last}" unless @options.hide_types
|
|
177
181
|
node_attribs << prop
|
|
178
182
|
end
|
|
179
183
|
end
|
|
@@ -205,8 +209,8 @@ class ModelsDiagram < AppDiagram
|
|
|
205
209
|
if @options.hide_magic
|
|
206
210
|
# From patch #13351
|
|
207
211
|
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
|
208
|
-
magic_fields = %w
|
|
209
|
-
content_columns = content_columns.
|
|
212
|
+
magic_fields = %w[created_at created_on updated_at updated_on lock_version _type _id position parent_id lft rgt quote template]
|
|
213
|
+
content_columns = content_columns.reject { |c| magic_fields.include?(c.name) }
|
|
210
214
|
end
|
|
211
215
|
|
|
212
216
|
content_columns.each do |a|
|
|
@@ -251,8 +255,8 @@ class ModelsDiagram < AppDiagram
|
|
|
251
255
|
content_columns = current_class.properties
|
|
252
256
|
|
|
253
257
|
if @options.hide_magic
|
|
254
|
-
magic_fields = %w
|
|
255
|
-
content_columns = content_columns.
|
|
258
|
+
magic_fields = %w[created_at updated_at type _id _rev]
|
|
259
|
+
content_columns = content_columns.reject { |c| magic_fields.include?(c.name) }
|
|
256
260
|
end
|
|
257
261
|
|
|
258
262
|
content_columns.each do |a|
|
|
@@ -269,11 +273,10 @@ class ModelsDiagram < AppDiagram
|
|
|
269
273
|
|
|
270
274
|
# Process a model association
|
|
271
275
|
def process_association(class_name, assoc)
|
|
272
|
-
|
|
273
|
-
|
|
276
|
+
warn "- Processing model association #{assoc.name}" if @options.verbose
|
|
274
277
|
# Skip "belongs_to" associations
|
|
275
|
-
macro = assoc.
|
|
276
|
-
return if %w
|
|
278
|
+
macro = assoc.methods.to_s
|
|
279
|
+
return if %w[belongs_to referenced_in].include?(macro) && !@options.show_belongs_to
|
|
277
280
|
|
|
278
281
|
# Skip "through" associations
|
|
279
282
|
through = assoc.options.include?(:through)
|
|
@@ -299,29 +302,30 @@ class ModelsDiagram < AppDiagram
|
|
|
299
302
|
if class_name.include?('::') && !assoc_class_name.include?('::')
|
|
300
303
|
assoc_class_name = class_name.split('::')[0..-2].push(assoc_class_name).join('::')
|
|
301
304
|
end
|
|
302
|
-
assoc_class_name.gsub
|
|
305
|
+
assoc_class_name = assoc_class_name.gsub(/^::/, '')
|
|
303
306
|
|
|
304
|
-
if %w
|
|
307
|
+
if %w[has_one references_one embeds_one].include?(macro)
|
|
305
308
|
assoc_type = 'one-one'
|
|
306
309
|
elsif macro == 'has_many' && (!assoc.options[:through]) ||
|
|
307
|
-
%w
|
|
310
|
+
%w[references_many embeds_many].include?(macro)
|
|
308
311
|
assoc_type = 'one-many'
|
|
309
312
|
elsif macro == 'belongs_to'
|
|
310
313
|
assoc_type = 'belongs-to'
|
|
311
314
|
else # habtm or has_many, :through
|
|
312
315
|
# Add FAKE associations too in order to understand mistakes
|
|
313
316
|
return if @habtm.include? [assoc_class_name, class_name, assoc_name]
|
|
317
|
+
|
|
314
318
|
assoc_type = 'many-many'
|
|
315
319
|
@habtm << [class_name, assoc_class_name, assoc_name]
|
|
316
320
|
end
|
|
317
321
|
# from patch #12384
|
|
318
322
|
# @graph.add_edge [assoc_type, class_name, assoc.class_name, assoc_name]
|
|
319
323
|
@graph.add_edge [assoc_type, class_name, assoc_class_name, assoc_name]
|
|
320
|
-
end
|
|
324
|
+
end
|
|
321
325
|
|
|
322
326
|
# Process a DataMapper relationship
|
|
323
327
|
def process_datamapper_relationship(class_name, relation)
|
|
324
|
-
|
|
328
|
+
warn "- Processing DataMapper model relationship #{relation.name}" if @options.verbose
|
|
325
329
|
|
|
326
330
|
# Skip "belongs_to" relationships
|
|
327
331
|
dm_type = relation.class.to_s.split('::')[-2]
|
|
@@ -354,4 +358,4 @@ class ModelsDiagram < AppDiagram
|
|
|
354
358
|
|
|
355
359
|
@graph.add_edge [rel_type, class_name, assoc_class_name, assoc_name]
|
|
356
360
|
end
|
|
357
|
-
end
|
|
361
|
+
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
# PrailRoady - RoR diagrams generator
|
|
2
3
|
# http://railroad.rubyforge.org
|
|
3
4
|
#
|
|
@@ -40,7 +41,7 @@ class OptionsStruct < OpenStruct
|
|
|
40
41
|
config_file: 'config/environment',
|
|
41
42
|
app_name: 'orailroady', app_human_name: 'PrailRoady', app_version: '', copyright: '' }
|
|
42
43
|
super(init_options.merge(args))
|
|
43
|
-
end
|
|
44
|
+
end
|
|
44
45
|
|
|
45
46
|
def parse(args)
|
|
46
47
|
@opt_parser = OptionParser.new do |opts|
|
|
@@ -138,11 +139,11 @@ class OptionsStruct < OpenStruct
|
|
|
138
139
|
opts.separator ''
|
|
139
140
|
opts.separator 'Other options:'
|
|
140
141
|
opts.on('-h', '--help', 'Show this message') do
|
|
141
|
-
|
|
142
|
+
$stdout.print "#{opts}\n"
|
|
142
143
|
exit
|
|
143
144
|
end
|
|
144
145
|
opts.on('--version', 'Show version and copyright') do
|
|
145
|
-
|
|
146
|
+
$stdout.print "#{app_human_name} version #{app_version}\n\n" \
|
|
146
147
|
"#{copyright}\nThis is free software; see the source " \
|
|
147
148
|
"for copying conditions.\n\n"
|
|
148
149
|
exit
|
|
@@ -154,7 +155,7 @@ class OptionsStruct < OpenStruct
|
|
|
154
155
|
opts.separator 'Commands (you must supply one of these):'
|
|
155
156
|
opts.on('-M', '--models', 'Generate models diagram') do |_c|
|
|
156
157
|
if command != ''
|
|
157
|
-
|
|
158
|
+
$stderr.print "Error: Can only generate one diagram type\n\n"
|
|
158
159
|
exit 1
|
|
159
160
|
else
|
|
160
161
|
self.command = 'models'
|
|
@@ -162,16 +163,16 @@ class OptionsStruct < OpenStruct
|
|
|
162
163
|
end
|
|
163
164
|
opts.on('-C', '--controllers', 'Generate controllers diagram') do |_c|
|
|
164
165
|
if command != ''
|
|
165
|
-
|
|
166
|
+
$stderr.print "Error: Can only generate one diagram type\n\n"
|
|
166
167
|
exit 1
|
|
167
168
|
else
|
|
168
169
|
self.command = 'controllers'
|
|
169
170
|
end
|
|
170
171
|
end
|
|
171
172
|
# From Ana Nelson's patch
|
|
172
|
-
opts.on('-A', '--aasm',
|
|
173
|
+
opts.on('-A', '--aasm', 'Generate "acts as state machine" diagram') do |_c|
|
|
173
174
|
if command == 'controllers'
|
|
174
|
-
|
|
175
|
+
$stderr.print "Error: Can only generate one diagram type\n\n"
|
|
175
176
|
exit 1
|
|
176
177
|
else
|
|
177
178
|
self.command = 'aasm'
|
|
@@ -180,7 +181,7 @@ class OptionsStruct < OpenStruct
|
|
|
180
181
|
opts.separator ''
|
|
181
182
|
opts.separator 'For bug reporting and additional information, please see:'
|
|
182
183
|
opts.separator 'http://railroad.rubyforge.org/'
|
|
183
|
-
end
|
|
184
|
+
end
|
|
184
185
|
|
|
185
186
|
begin
|
|
186
187
|
@opt_parser.parse!(args)
|
|
@@ -193,12 +194,12 @@ class OptionsStruct < OpenStruct
|
|
|
193
194
|
rescue OptionParser::MissingArgument
|
|
194
195
|
option_error 'Missing argument'
|
|
195
196
|
end
|
|
196
|
-
end
|
|
197
|
+
end
|
|
197
198
|
|
|
198
199
|
private
|
|
199
200
|
|
|
200
201
|
def option_error(msg)
|
|
201
|
-
|
|
202
|
+
$stderr.print "Error: #{msg}\n\n #{@opt_parser}\n"
|
|
202
203
|
exit 1
|
|
203
204
|
end
|
|
204
|
-
end
|
|
205
|
+
end
|
data/lib/prailroady/version.rb
CHANGED
data/lib/prailroady.rb
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require 'prailroady/version'
|
|
4
|
+
require 'prailroady/options_struct'
|
|
5
|
+
require 'prailroady/models_diagram'
|
|
6
|
+
require 'prailroady/controllers_diagram'
|
|
7
|
+
require 'prailroady/aasm_diagram'
|
|
8
|
+
|
|
9
|
+
# This is the RailRoady module
|
|
10
|
+
# TODO: documentation
|
|
11
|
+
module RailRoady
|
|
4
12
|
require 'prailroady/railtie' if defined?(Rails)
|
|
5
13
|
end
|
data/prailroady.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prailroady
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SaKKo
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-03-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -118,7 +118,7 @@ homepage: http://github.com/sakko/prailroady
|
|
|
118
118
|
licenses:
|
|
119
119
|
- GPL-2.0
|
|
120
120
|
metadata: {}
|
|
121
|
-
post_install_message:
|
|
121
|
+
post_install_message:
|
|
122
122
|
rdoc_options: []
|
|
123
123
|
require_paths:
|
|
124
124
|
- lib
|
|
@@ -133,9 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
133
133
|
- !ruby/object:Gem::Version
|
|
134
134
|
version: '0'
|
|
135
135
|
requirements: []
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
signing_key:
|
|
136
|
+
rubygems_version: 3.2.22
|
|
137
|
+
signing_key:
|
|
139
138
|
specification_version: 4
|
|
140
139
|
summary: Ruby on Rails 3/4/5 model UML class diagram generator.
|
|
141
140
|
test_files:
|