umlify 0.3.3 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,114 @@
1
+ _ _ __
2
+ | (_)/ _|
3
+ _ _ _ __ ___ | |_| |_ _ _
4
+ | | | | '_ ` _ \| | | _| | | |
5
+ | |_| | | | | | | | | | | |_| |
6
+ \__,_|_| |_| |_|_|_|_| \__, |
7
+ __/ |
8
+ |___/
9
+
10
+ umlify is a tool that creates
11
+ uml class diagrams from your code
12
+
13
+ <https://github.com/mikaa123/umlify>
14
+
15
+ Introduction
16
+ ------------
17
+
18
+ umlify takes your ruby project's source code and creates an uml class diagram out of it.
19
+
20
+ Installation
21
+ ------------
22
+
23
+ gem install umlify
24
+
25
+ How to use
26
+ ----------
27
+
28
+ 1. Go to your gem project directory
29
+ 2. type: `umlify lib/*/*`
30
+ 3. Open uml.html
31
+
32
+ Example
33
+ -------
34
+
35
+ Here is umlify umlified:
36
+
37
+ ![umlify's uml](http://img43.imageshack.us/img43/2756/umlify.png)
38
+
39
+ Features
40
+ --------
41
+
42
+ * __new__ now supports inhertiance (v0.4.2)
43
+ * supports associations (see "How to add associations to a diagram)
44
+ * supports methods and instance variables
45
+
46
+ How it works
47
+ ------------
48
+
49
+ umlify parses your source codes using regular expressions to build an uml
50
+ diagram using [yUML](http://yuml.me/)'s api.
51
+
52
+ Note: Regexps parsing is really dirty. This point needs serious
53
+ improvement
54
+
55
+ On dynamic languages
56
+ --------------------
57
+
58
+ Ruby's extreme decoupling and duck-typing philosophy doesn't judge a class by its hierarchy.
59
+ Thus, variables don't have a predefined type, which conflicts with uml's static typed object-model.
60
+ The objective of this project isn't to bend uml's model to make it semantically comply with
61
+ duck typing (by the use of interfaces, or other tricks), but to add a basic visual representation
62
+ of the code of your project for documenting and helping maintainers.
63
+
64
+ How to add associations to a diagram
65
+ ------------------------------------
66
+
67
+ Because of the above point, there's no direct way to automatically draw associations between your
68
+ classes. However, if you want an association to be shown on your diagram simply add an annotation
69
+ on top of an `attr_accessor`, such as:
70
+
71
+ # type: Unicorn
72
+ attr_accessor :animal
73
+
74
+ Contribute
75
+ ----------
76
+
77
+ If you are interested by this project (I hope you are!), you can send me your comments
78
+ (mikaa123 at gmail), test the application and create some issue when you find a bug.
79
+
80
+ If you want to contribute, you can check the TODO, it's a good place to start. :)
81
+ Just fork and send a pull request. I'd love to have some help.
82
+
83
+ Not having the expected results?
84
+ --------------------------------
85
+
86
+ If you have found a bug, or if the results you obtained don't correspond
87
+ to your code, you can raise an issue and link to your github project
88
+ page.
89
+
90
+ Real project testing is way more efficient than on test cases. :)
91
+
92
+ License
93
+ -------
94
+
95
+ Copyright (C) 2011 Michael Sokol
96
+
97
+ Permission is hereby granted, free of charge, to any person obtaining a copy
98
+ of this software and associated documentation files (the "Software"), to deal
99
+ in the Software without restriction, including without limitation the rights
100
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101
+ copies of the Software, and to permit persons to whom the Software is
102
+ furnished to do so, subject to the following conditions:
103
+
104
+ The above copyright notice and this permission notice shall be included in
105
+ all copies or substantial portions of the Software.
106
+
107
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
108
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
109
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
110
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
111
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
112
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
113
+ THE SOFTWARE.
114
+
@@ -17,17 +17,20 @@ module Umlify
17
17
  end
18
18
 
19
19
  # Adds the given statement to the @diagram array
20
+ # Statement can either be a String or an UmlClass
20
21
  def add statement
21
22
  # TODO: Add some sort of validation
22
23
 
23
24
  @statements << statement if statement.is_a? String
24
25
  if statement.is_a? UmlClass
25
26
 
26
- if statement.associations.empty?
27
- @statements << statement.to_s
28
- else
29
- @statements << statement.to_s
27
+ @statements << statement.to_s
30
28
 
29
+ if statement.parent
30
+ @statements << "[#{statement.parent}]^[#{statement.name}]"
31
+ end
32
+
33
+ unless statement.associations.empty?
31
34
  statement.associations.each do |name, type|
32
35
  @statements << "[#{statement.name}]-#{name}>[#{type}]"
33
36
  end
@@ -36,9 +39,9 @@ module Umlify
36
39
  end
37
40
  end
38
41
 
39
- # Dumps the html of the diagram
40
- def export
41
- '<img src="http://yuml.me/diagram/class/'+@statements.join(", ")+'" />'
42
+ # Returns the yuml.me uri
43
+ def get_uri
44
+ uri = '/diagram/class/'+@statements.join(", ")
42
45
  end
43
46
  end
44
47
  end
data/lib/umlify/parser.rb CHANGED
@@ -26,6 +26,7 @@ module Umlify
26
26
  return nil if @source_files.empty?
27
27
 
28
28
  @source_files.each do |file|
29
+ puts "processing #{file}..."
29
30
  f = File.open file, 'r'
30
31
  (parse_file f).each {|c| @classes << c}
31
32
  f.close
@@ -43,11 +44,18 @@ module Umlify
43
44
  file.each do |line|
44
45
 
45
46
  # This parses the classes
46
- line.match(/^\s*class ([\w]*)\b/) do |m|
47
+ line.match(/^\s*class ([\w]*)\b[\s]*$/) do |m|
47
48
  current_class = UmlClass.new m[1]
48
49
  classes_in_file << current_class
49
50
  end
50
51
 
52
+ # This parses the classes and its parent (class Foo < Bar)
53
+ line.match(/^\s*class ([\w]*) < ([\w]*)\b/) do |m|
54
+ current_class = UmlClass.new m[1]
55
+ current_class.parent = m[2]
56
+ classes_in_file << current_class
57
+ end
58
+
51
59
  if current_class
52
60
 
53
61
  # This parses the @variables
@@ -65,8 +73,8 @@ module Umlify
65
73
 
66
74
  # This adds an association to the current class, using the type_annotation
67
75
  # if type_annotation has been set
68
- line.match(/attr_accessor :([\w]*)\b/) do |m|
69
- current_class.associations[m[1]] = type_annotation
76
+ line.match(/(attr_accessor|attr_reader|attr_writer) :([\w]*)\b/) do |m|
77
+ current_class.associations[m[2]] = type_annotation
70
78
  type_annotation = nil
71
79
  end if type_annotation
72
80
 
data/lib/umlify/runner.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'optparse'
2
+ require 'net/http'
2
3
 
3
4
  module Umlify
4
5
 
@@ -28,7 +29,7 @@ module Umlify
28
29
  if @args[0][0] == '-'
29
30
 
30
31
  OptionParser.new do |opts|
31
- opts.banner = "Usage: umlify [option]"
32
+ opts.banner = "Usage: umlify [option] [source-files directory]"
32
33
  opts.on("-h", "--help", "Shows this") do
33
34
  puts opts
34
35
  end
@@ -36,37 +37,33 @@ module Umlify
36
37
 
37
38
  else
38
39
  puts "umlifying"
39
- if files = get_files_from_dir(@args[0])
40
- puts "about to parse..."
41
- @parser = Parser.new files
42
40
 
43
- if classes = @parser.parse_sources!
44
- @diagram = Diagram.new
41
+ @parser = Parser.new @args
45
42
 
46
- @diagram.create do
47
- classes.each {|c| add c}
48
- end
43
+ if classes = @parser.parse_sources!
44
+ @diagram = Diagram.new
49
45
 
50
- File.open("uml.html", 'w') do |file|
51
- file << @diagram.export
52
- end
46
+ @diagram.create do
47
+ classes.each {|c| add c}
48
+ end
49
+
50
+ puts "Downloading the image from yUML, it shouldn't be long."
53
51
 
54
- puts "Saved in uml.html"
55
- else
56
- puts "No ruby files in the directory"
52
+ image = Net::HTTP.start("yuml.me", 80) do |http|
53
+ http.get(URI.escape(@diagram.get_uri))
57
54
  end
58
55
 
56
+ File.open('uml.png', 'wb') do |file|
57
+ file << image.body
58
+ end if image
59
+
60
+ puts "Saved in uml.png"
59
61
  else
60
- puts "empty directory"
62
+ puts "No ruby files in the directory"
61
63
  end
62
- end
63
64
 
64
- end
65
-
66
- private
65
+ end
67
66
 
68
- def get_files_from_dir directory
69
- Dir[directory] unless Dir[directory].empty?
70
67
  end
71
68
  end
72
69
  end
@@ -4,7 +4,7 @@ module Umlify
4
4
  # Represent a parsed uml class
5
5
  #
6
6
  class UmlClass
7
- attr_accessor :name, :variables, :methods, :associations
7
+ attr_accessor :name, :variables, :methods, :associations, :parent
8
8
 
9
9
  def initialize name
10
10
  @name = name
@@ -1,3 +1,3 @@
1
1
  module Umlify
2
- VERSION = "0.3.3"
2
+ VERSION = "0.6.1"
3
3
  end
data/lib/umlify.rb CHANGED
@@ -1,3 +1,35 @@
1
+ # _ _ __
2
+ # | (_)/ _|
3
+ # _ _ _ __ ___ | |_| |_ _ _
4
+ # | | | | '_ ` _ \| | | _| | | |
5
+ # | |_| | | | | | | | | | | |_| |
6
+ # \__,_|_| |_| |_|_|_|_| \__, |
7
+ # __/ |
8
+ # |___/
9
+ #
10
+ #
11
+ # umlify is tool that generates uml from your ruby source files. It
12
+ # works using yUML.me web api.
13
+ #
14
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ # of this software and associated documentation files (the "Software"), to deal
16
+ # in the Software without restriction, including without limitation the rights
17
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ # copies of the Software, and to permit persons to whom the Software is
19
+ # furnished to do so, subject to the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be included in
22
+ # all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30
+ # THE SOFTWARE.
31
+
32
+
1
33
  require 'umlify/version'
2
34
  require 'umlify/runner'
3
35
  require 'umlify/parser'
data/test/diagram_test.rb CHANGED
@@ -50,17 +50,31 @@ class DiagramTest < Test::Unit::TestCase
50
50
  assert @diagram.statements.include? '[Unicorn]-chunky>[Bacon]'
51
51
  end
52
52
 
53
- should "export th yUML html" do
53
+ should "add UmlClass with parent to diagrams" do
54
54
  test_uml_class = Umlify::UmlClass.new 'Unicorn'
55
55
  test_uml_class.variables << 'foo_variable'
56
56
  test_uml_class.methods << 'bar_method'
57
+ test_uml_class.parent = "Foo"
57
58
 
58
59
  @diagram.create do
59
60
  add test_uml_class
60
61
  end
61
62
 
62
- assert_equal '<img src="http://yuml.me/diagram/class/[Unicorn|foo_variable|bar_method]" />',
63
- @diagram.export
63
+ assert @diagram.statements.include? '[Unicorn|foo_variable|bar_method]'
64
+ assert @diagram.statements.include? '[Foo]^[Unicorn]'
65
+ end
66
+
67
+ should "get the yuml uri" do
68
+ test_uml_class = Umlify::UmlClass.new 'Unicorn'
69
+ test_uml_class.variables << 'foo_variable'
70
+ test_uml_class.methods << 'bar_method'
71
+
72
+ @diagram.create do
73
+ add test_uml_class
74
+ end
75
+
76
+ assert_equal '/diagram/class/[Unicorn|foo_variable|bar_method]',
77
+ @diagram.get_uri
64
78
  end
65
79
 
66
80
  end
data/test/parser_test.rb CHANGED
@@ -27,6 +27,14 @@ class ParserTest < Test::Unit::TestCase
27
27
  assert_equal 'AClassName', @p.parse_file(test)[0].name
28
28
  end
29
29
 
30
+ should "parse class name of inherited classes" do
31
+ test = <<-END_FILE
32
+ class AClassName < SuperClass
33
+ end
34
+ END_FILE
35
+ assert_equal 'AClassName', @p.parse_file(test)[0].name
36
+ end
37
+
30
38
  should "parse @variables in classes" do
31
39
  test = <<-END_FILE
32
40
  class Bar
@@ -56,6 +64,57 @@ class ParserTest < Test::Unit::TestCase
56
64
  assert_equal "FooBar", bar.associations['unicorn']
57
65
  end
58
66
 
67
+ should "parse attr_reader when preceeded by a # type: Type annotation" do
68
+ test = <<-END_FILE
69
+ class Bar
70
+
71
+ # type: FooBar
72
+ attr_reader :unicorn
73
+
74
+ def foo
75
+ end
76
+ end
77
+ END_FILE
78
+ bar = @p.parse_file(test)[0]
79
+ assert_instance_of Umlify::UmlClass, bar
80
+ assert_equal "FooBar", bar.associations['unicorn']
81
+ end
82
+
83
+
84
+ should "parse attr_writer when preceeded by a # type: Type annotation" do
85
+ test = <<-END_FILE
86
+ class Bar
87
+
88
+ # type: FooBar
89
+ attr_writer :unicorn
90
+
91
+ def foo
92
+ end
93
+ end
94
+ END_FILE
95
+ bar = @p.parse_file(test)[0]
96
+ assert_instance_of Umlify::UmlClass, bar
97
+ assert_equal "FooBar", bar.associations['unicorn']
98
+ end
99
+
100
+ should "parse inherited classes" do
101
+ test = <<-END_FILE
102
+ class Bar < Hash
103
+
104
+ def initialize
105
+ end
106
+
107
+ def save
108
+ end
109
+
110
+ end
111
+ end
112
+ END_FILE
113
+ bar = @p.parse_file(test)[0]
114
+ assert_instance_of Umlify::UmlClass, bar
115
+ assert_equal "Hash", bar.parent
116
+ end
117
+
59
118
  should "return an array of UmlClasses when the parsing is done" do
60
119
  p = Umlify::Parser.new Dir[File.dirname(__FILE__)+'/fixtures/*']
61
120
  parsed_classes = p.parse_sources!
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: umlify
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.3
5
+ version: 0.6.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Michael Sokol
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-02 00:00:00 -05:00
13
+ date: 2011-03-04 00:00:00 -05:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -24,7 +24,7 @@ extra_rdoc_files: []
24
24
 
25
25
  files:
26
26
  - Rakefile
27
- - README
27
+ - README.md
28
28
  - bin/umlify
29
29
  - lib/umlify.rb
30
30
  - lib/umlify/version.rb
data/README DELETED
@@ -1,19 +0,0 @@
1
- _ _ __
2
- | (_)/ _|
3
- _ _ _ __ ___ | |_| |_ _ _
4
- | | | | '_ ` _ \| | | _| | | |
5
- | |_| | | | | | | | | | | |_| |
6
- \__,_|_| |_| |_|_|_|_| \__, |
7
- __/ |
8
- |___/
9
-
10
- umlify is a tool that creates
11
- uml class diagrams from your code
12
-
13
- <https://github.com/mikaa123/umlify>
14
-
15
-
16
- Introduction
17
- ------------
18
-
19
- umlify takes your project's source code and creates an uml class diagram out of it.