dm-visualizer 0.1.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.
@@ -0,0 +1,67 @@
1
+ require 'dm-visualizer/rake/task'
2
+ require 'dm-visualizer/graphviz'
3
+
4
+ module DataMapper
5
+ module Visualizer
6
+ module Rake
7
+ class GraphVizTask < Task
8
+
9
+ # The relational diagram GraphViz visualizer
10
+ attr_reader :relational
11
+
12
+ # The schema diagram GraphViz visualizer
13
+ attr_reader :schema
14
+
15
+ #
16
+ # Creates a new `dm:doc:graphviz` task.
17
+ #
18
+ # @param [Hash] options
19
+ # Additional options.
20
+ #
21
+ # @yield [task]
22
+ # The given block will be passed the newly created task.
23
+ #
24
+ # @yieldparam [GraphVizTask] task
25
+ # The new GraphViz task.
26
+ #
27
+ # @see GraphViz.new
28
+ #
29
+ def initialize(options={})
30
+ @relational = GraphViz.new(options.merge(
31
+ :naming => :relational,
32
+ :file => 'doc/relational_diagram'
33
+ ))
34
+
35
+ @schema = GraphViz.new(options.merge(
36
+ :naming => :schema,
37
+ :file => 'doc/schema_diagram'
38
+ ))
39
+
40
+ super
41
+ end
42
+
43
+ #
44
+ # Defines the `dm:doc:graphviz` namespace.
45
+ #
46
+ def define
47
+ super do
48
+ namespace :graphviz do
49
+ desc 'Generates a GraphViz relational diagram of the DataMapper Models'
50
+ task :relational do
51
+ @relational.visualize!
52
+ end
53
+
54
+ desc 'Generates a GraphViz schema diagram of the DataMapper Models'
55
+ task :schema do
56
+ @schema.visualize!
57
+ end
58
+ end
59
+
60
+ task :graphviz => ['graphviz:relational', 'graphviz:schema']
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,16 @@
1
+ require 'dm-visualizer/rake/rails/tasks'
2
+ require 'dm-visualizer/rake/graphviz_task'
3
+
4
+ module DataMapper
5
+ module Visualizer
6
+ module Rake
7
+ module Rails
8
+ class GraphVizTask < Rake::GraphVizTask
9
+
10
+ include Tasks
11
+
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ module DataMapper
2
+ module Visualizer
3
+ module Rake
4
+ module Rails
5
+ module Tasks
6
+ #
7
+ # Overrides the Rake `task` method to make sure every defined
8
+ # task depends on `dm:load_models`.
9
+ #
10
+ # @param [Array] arguments
11
+ # The arguments of the task.
12
+ #
13
+ def task(*arguments)
14
+ if arguments.first.kind_of?(Hash)
15
+ super(*arguments)
16
+ else
17
+ super(arguments.first => 'db:load_models')
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ require 'rake'
2
+
3
+ module DataMapper
4
+ module Visualizer
5
+ module Rake
6
+ class Task < ::Rake::TaskLib
7
+ #
8
+ # Creates a new task.
9
+ #
10
+ # @yield [task]
11
+ # The given block will be passed the newly created task.
12
+ #
13
+ # @yieldparam [Task] task
14
+ # The new Task.
15
+ #
16
+ def initialize(options={})
17
+ yield self if block_given?
18
+
19
+ define()
20
+ end
21
+
22
+ #
23
+ # Defines a task within the `dm:doc` namespace.
24
+ #
25
+ def define(&block)
26
+ namespace :dm do
27
+ namespace(:doc,&block)
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,204 @@
1
+ require 'dm-visualizer/project'
2
+
3
+ require 'dm-core'
4
+
5
+ module DataMapper
6
+ module Visualizer
7
+ #
8
+ # The base class for all visualizations.
9
+ #
10
+ class Visualization
11
+
12
+ # The inflector to use
13
+ Inflector = if Object.const_defined?('ActiveSupport')
14
+ ActiveSupport::Inflector
15
+ else
16
+ Extlib::Inflection
17
+ end
18
+
19
+ # The project that will be visualized
20
+ attr_reader :project
21
+
22
+ # Mapping of DataMapper repository names and their actual names.
23
+ attr_reader :repository_names
24
+
25
+ # Specifies which naming convention to use
26
+ # (`:relational` or `:schema`).
27
+ attr_accessor :naming
28
+
29
+ # Specifies whether to demodulize class names.
30
+ attr_accessor :full_names
31
+
32
+ #
33
+ # Initializes a new visualization.
34
+ #
35
+ # @param [Hash] options
36
+ # Additional options.
37
+ #
38
+ # @option options [Hash] :repository_names
39
+ # The actual names of the DataMapper repositories.
40
+ #
41
+ # @option options [String] :repository_name
42
+ # The actual name to use for the `:default` DataMappe repository.
43
+ #
44
+ # @option options [Symbol] :naming
45
+ # The naming convention to use. May be either `:relational` or
46
+ # `:schema`.
47
+ #
48
+ # @option options [Boolean] :full_names
49
+ # Specifies whether to demodulize class names.
50
+ #
51
+ def initialize(options={})
52
+ @project = Project.new(options)
53
+
54
+ @repository_names = {}
55
+ @naming = :relational
56
+ @full_names = false
57
+
58
+ if options[:repository_names]
59
+ options[:repository_names].each do |name,db_name|
60
+ @repository_names[name.to_sym] = db_name.to_s
61
+ end
62
+ end
63
+
64
+ if options[:repository_name]
65
+ @database_names[:default] = options[:repository_name].to_s
66
+ end
67
+
68
+ if options[:naming]
69
+ @naming = options[:naming].to_sym
70
+ end
71
+
72
+ if options.has_key?(:full_names)
73
+ @full_names = options[:full_names]
74
+ end
75
+ end
76
+
77
+ #
78
+ # Returns the class name of a given object.
79
+ #
80
+ # @param [Class, Object] obj
81
+ # The object or class.
82
+ #
83
+ # @return [String]
84
+ # The class name of the object or class.
85
+ #
86
+ def class_name(obj)
87
+ name = if (obj.class == Class || obj.class == Module)
88
+ obj.name
89
+ else
90
+ obj.class.name
91
+ end
92
+
93
+ name = Inflector.demodulize(name) unless @full_names
94
+
95
+ return name
96
+ end
97
+
98
+ #
99
+ # Returns the name of a given property.
100
+ #
101
+ # @param [DataMapper::Property] property
102
+ # The property.
103
+ #
104
+ # @return [String]
105
+ # The property name.
106
+ #
107
+ def property_name(property)
108
+ property.name.to_s
109
+ end
110
+
111
+ #
112
+ # Returns the name the given foreign key.
113
+ #
114
+ # @param [Symbol] key
115
+ # The foreign key.
116
+ #
117
+ # @return [String]
118
+ # The foreign key name.
119
+ #
120
+ def foreign_key_name(key)
121
+ key = key.to_s
122
+
123
+ key.chomp!('_id') unless @naming == :schema
124
+ return key
125
+ end
126
+
127
+ #
128
+ # Returns the type name of a property.
129
+ #
130
+ # @param [DataMapper::Property] property
131
+ # The property.
132
+ #
133
+ # @return [String]
134
+ # The property type name.
135
+ #
136
+ def property_type_name(property)
137
+ class_name(property.type || property.class)
138
+ end
139
+
140
+ #
141
+ # Returns the repository name of a model.
142
+ #
143
+ # @param [DataMapper::Model] model
144
+ # The model.
145
+ #
146
+ # @return [String]
147
+ # The repository name.
148
+ #
149
+ def model_repository_name(model)
150
+ @repository_names[model.default_repository_name]
151
+ end
152
+
153
+ #
154
+ # Returns the name of a model.
155
+ #
156
+ # @param [DataMapper::Model] model
157
+ # The model.
158
+ #
159
+ # @return [String]
160
+ # The name of the model.
161
+ #
162
+ def model_name(model)
163
+ if @naming == :schema
164
+ name = model_repository_name(model)
165
+ storage_name = model.storage_names[:default]
166
+ storage_name ||= NamingConventions::Resource::UnderscoredAndPluralized.call(model.name)
167
+
168
+ if name
169
+ "#{name}.#{storage_name}"
170
+ else
171
+ storage_name
172
+ end
173
+ else
174
+ class_name(model)
175
+ end
176
+ end
177
+
178
+ #
179
+ # Loads the project and visualizes it.
180
+ #
181
+ # @param [Array] arguments
182
+ # Additional arguments to pass to {#visualize}.
183
+ #
184
+ def visualize!(*arguments)
185
+ @project.load!
186
+
187
+ visualize(*arguments)
188
+ end
189
+
190
+ protected
191
+
192
+ #
193
+ # Default method which visualizes the DataMapper models, properties
194
+ # and relationships.
195
+ #
196
+ # @param [Project] project
197
+ # The project to visualize.
198
+ #
199
+ def visualize
200
+ end
201
+
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,9 @@
1
+ require 'dm-visualizer'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe DataMapper::Visualizer do
6
+ it "should define a VERSION constant" do
7
+ DataMapper::Visualizer.const_defined?('VERSION').should == true
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Helpers
2
+ module Project
3
+ PROJECTS_DIR = File.expand_path(File.join(File.dirname(__FILE__),'projects'))
4
+
5
+ def project_dir(name)
6
+ File.join(PROJECTS_DIR,name)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ require 'blog/user'
2
+ require 'blog/post'
3
+ require 'blog/comment'
@@ -0,0 +1,17 @@
1
+ require 'blog/post'
2
+
3
+ require 'dm-core'
4
+
5
+ module Blog
6
+ class Comment
7
+
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+
12
+ property :body, Text
13
+
14
+ belongs_to :post
15
+
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'blog/user'
2
+
3
+ require 'dm-core'
4
+
5
+ module Blog
6
+ class Post
7
+
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+
12
+ property :title, String
13
+
14
+ property :body, Text
15
+
16
+ belongs_to :user
17
+
18
+ has 0..n, :comments
19
+
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ require 'blog/post'
2
+
3
+ require 'dm-core'
4
+
5
+ module Blog
6
+ class User
7
+
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+
12
+ property :name, String
13
+
14
+ has 0..n, :posts
15
+
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class Comment
2
+
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+
7
+ property :body, Text
8
+
9
+ belongs_to :post
10
+
11
+ end