netsign-annotate 2.4.4

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/History.txt ADDED
@@ -0,0 +1,37 @@
1
+ == 2.1 2009-10-18
2
+
3
+ * New options
4
+ * -R to require additional files before loading the models
5
+ * -i to show database indexes in annotations
6
+ * -e to exclude annotating tests or fixtures
7
+ * -m to include the migration version number in the annotation
8
+ * --model-dir to annotate model files stored a different place than app/models
9
+ * Ignore unknown macros ('acts_as_whatever')
10
+
11
+ == 2.0 2009-02-03
12
+
13
+ * Add annotate_models plugin fork additions
14
+ * Annotates Rspec and Test Unit models
15
+ * Annotates Object Daddy exemplars
16
+ * Annotates geometrical columns
17
+ * Add AnnotateRoutes rake task
18
+ * Up gem structure to newgem defaults
19
+
20
+ == 1.0.4 2008-09-04
21
+
22
+ * Only update modified models since last run, thanks to sant0sk1
23
+
24
+ == 1.0.3 2008-05-02
25
+
26
+ * Add misc changes from Dustin Sallings and Henrik N
27
+ * Remove trailing whitespace
28
+ * More intuitive info messages
29
+ * Update README file with update-to-date example
30
+
31
+ == 1.0.2 2008-03-22
32
+
33
+ * Add contributions from Michael Bumann (http://github.com/bumi)
34
+ * added an option "position" to choose to put the annotation,
35
+ * spec/fixtures now also get annotated
36
+ * added a task to remove the annotations
37
+ * these options can be specified from command line as -d and -p [before|after]
data/README.rdoc ADDED
@@ -0,0 +1,138 @@
1
+ == Annotate (aka AnnotateModels)
2
+
3
+ Add a comment summarizing the current schema to the top or bottom of each of your...
4
+
5
+ * ActiveRecord models
6
+ * Fixture files
7
+ * Tests and Specs
8
+ * Object Daddy exemplars
9
+ * Machinist blueprints
10
+
11
+ The schema comment looks like this:
12
+
13
+ # == Schema Info
14
+ #
15
+ # Table name: line_items
16
+ #
17
+ # id :integer(11) not null, primary key
18
+ # quantity :integer(11) not null
19
+ # product_id :integer(11) not null
20
+ # unit_price :float
21
+ # order_id :integer(11)
22
+ #
23
+
24
+ class LineItem < ActiveRecord::Base
25
+ belongs_to :product
26
+ . . .
27
+
28
+ It also annotates geometrical columns, geom type and srid, when using SpatialAdapter or PostgisAdapter:
29
+
30
+ # == Schema Info
31
+ #
32
+ # Table name: trips
33
+ #
34
+ # local :geometry point, 4326
35
+ # path :geometry line_string, 4326
36
+
37
+ Also, if you pass the -r option, it'll annotate routes.rb with the output of "rake routes".
38
+
39
+ == INSTALL
40
+
41
+ From rubyforge:
42
+
43
+ sudo gem install annotate
44
+
45
+ From github:
46
+
47
+ git clone git://github.com/ctran/annotate_models.git annotate
48
+ cd annotate
49
+ rake gem
50
+ sudo gem install pkg/annotate-*.gem
51
+
52
+ == USAGE
53
+
54
+ To annotate all your models, tests, fixtures, etc.:
55
+
56
+ cd /path/to/app
57
+ annotate
58
+
59
+ To annotate your models and tests:
60
+
61
+ annotate --exclude fixtures
62
+
63
+ To annotate just your models:
64
+
65
+ annotate --exclude tests,fixtures
66
+
67
+ To annotate routes.rb:
68
+
69
+ annotate -r
70
+
71
+ To automatically annotate after running 'rake db:migrate':
72
+
73
+ [needs more clarity] unpack the gem into vendor/plugins, or maybe vendor/gems, or maybe just require tasks/migrate.rake.
74
+
75
+ If you install annotate_models as a plugin, it will automatically
76
+ adjust your <tt>rake db:migrate</tt> tasks so that they update the
77
+ annotations in your model files for you once the migration is
78
+ completed.
79
+
80
+ == OPTIONS
81
+
82
+ Usage: annotate [options] [model_file]*
83
+ -d, --delete Remove annotations from all model files
84
+ -p, --position [before|after] Place the annotations at the top (before) or the bottom (after) of the model file
85
+ -r, --routes Annotate routes.rb with the output of 'rake routes'
86
+ -v, --version Show the current version of this gem
87
+ -m, --show-migration Include the migration version number in the annotation
88
+ -i, --show-indexes List the table's database indexes in the annotation
89
+ -s, --simple-indexes Concat the column's related indexes in the annotation
90
+ --model-dir dir Annotate model files stored in dir rather than app/models
91
+ -R, --require path Additional files to require before loading models
92
+ -e, --exclude [tests,fixtures] Do not annotate fixtures, test files, or both
93
+
94
+
95
+ == WARNING
96
+
97
+ Note that this code will blow away the initial/final comment
98
+ block in your models if it looks like it was previously added
99
+ by annotate models, so you don't want to add additional text
100
+ to an automatically created comment block.
101
+
102
+ * * Back up your model files before using... * *
103
+
104
+ == LINKS
105
+
106
+ * Factory Girl => http://github.com/thoughtbot/factory_girl (NOT IMPLEMENTED)
107
+ * Object Daddy => http://github.com/flogic/object_daddy
108
+ * SpatialAdapter => http://github.com/pdeffendol/spatial_adapter
109
+ * PostgisAdapter => http://github.com/nofxx/postgis_adapter
110
+
111
+ == LICENSE:
112
+
113
+ Released under the same license as Ruby. No Support. No Warranty.
114
+
115
+ == AUTHOR:
116
+
117
+ Original code by: Dave Thomas -- Pragmatic Programmers, LLC
118
+ Overhauled by: Alex Chaffee
119
+ Gemmed by: Cuong Tran
120
+ Maintained by: Alex Chaffee and Cuong Tran
121
+
122
+ Modifications by:
123
+
124
+ - Alex Chaffee - http://github.com/alexch - alex@pivotallabs.com
125
+ - Cuong Tran - http://github.com/ctran - ctran@pragmaquest.com
126
+ - Jack Danger - http://github.com/JackDanger
127
+ - Michael Bumann - http://github.com/bumi
128
+ - Henrik Nyh - http://github.com/henrik
129
+ - Marcos Piccinini - http://github.com/nofxx
130
+ - Neal Clark - http://github.com/nclark
131
+ - Jacqui Maher - http://github.com/jacqui
132
+ - Nick Plante - http://github.com/zapnap - http://blog.zerosum.org
133
+ - Pedro Visintin - http://github.com/peterpunk - http://www.pedrovisintin.com
134
+ - Bob Potter - http://github.com/bpot
135
+ - Gavin Montague - http://github.com/govan/
136
+ - Alexander Semyonov - http://github.com/rotuka/
137
+
138
+ and many others that I may have missed to add.
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 2
3
+ :build:
4
+ :minor: 4
5
+ :patch: 4
data/bin/annotate ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'annotate'
5
+
6
+ task = :annotate_models
7
+
8
+ OptionParser.new do |opts|
9
+ opts.banner = "Usage: annotate [options] [model_file]*"
10
+
11
+ opts.on('-d', '--delete',
12
+ "Remove annotations from all model files") do
13
+ task = :remove_annotation
14
+ end
15
+
16
+ opts.on('-p', '--position [before|after]', ['before', 'after'],
17
+ "Place the annotations at the top (before) or the bottom (after) of the model file") do |p|
18
+ ENV['position'] = p
19
+ end
20
+
21
+ opts.on('-r', '--routes',
22
+ "Annotate routes.rb with the output of 'rake routes'") do
23
+ task = :annotate_routes
24
+ end
25
+
26
+ opts.on('-v', '--version',
27
+ "Show the current version of this gem") do
28
+ puts "annotate v#{Annotate.version}"; exit
29
+ end
30
+
31
+ opts.on('-m', '--show-migration',
32
+ "Include the migration version number in the annotation") do
33
+ ENV['include_version'] = "yes"
34
+ end
35
+
36
+ opts.on('-i', '--show-indexes',
37
+ "List the table's database indexes in the annotation") do
38
+ ENV['show_indexes'] = "yes"
39
+ end
40
+
41
+ opts.on('-s', '--simple-indexes',
42
+ "Concat the column's related indexes in the annotation") do
43
+ ENV['simple_indexes'] = "yes"
44
+ end
45
+
46
+ opts.on('--model-dir dir',
47
+ "Annotate model files stored in dir rather than app/models") do |dir|
48
+ ENV['model_dir'] = dir
49
+ end
50
+
51
+ opts.on('-R', '--require path',
52
+ "Additional files to require before loading models") do |path|
53
+ if ENV['require']
54
+ ENV['require'] = ENV['require'] + ",#{path}"
55
+ else
56
+ ENV['require'] = path
57
+ end
58
+ end
59
+
60
+ opts.on('-e', '--exclude [tests,fixtures]', Array, "Do not annotate fixtures, test files, or both") do |exclusions|
61
+ exclusions.each { |exclusion| ENV["exclude_#{exclusion}"] = "yes" }
62
+ end
63
+
64
+ end.parse!
65
+
66
+ if Annotate.load_tasks
67
+ Rake::Task[task].invoke
68
+ else
69
+ STDERR.puts "Can't find Rakefile. Are we in a Rails folder?"
70
+ end
@@ -0,0 +1,333 @@
1
+ module AnnotateModels
2
+ class << self
3
+ # Annotate Models plugin use this header
4
+ COMPAT_PREFIX = "== Schema Info"
5
+ PREFIX = "== Schema Information"
6
+
7
+ FIXTURE_DIRS = ["test/fixtures","spec/fixtures"]
8
+ # File.join for windows reverse bar compat?
9
+ # I dont use windows, can`t test
10
+ UNIT_TEST_DIR = File.join("test", "unit" )
11
+ SPEC_MODEL_DIR = File.join("spec", "models")
12
+ # Object Daddy http://github.com/flogic/object_daddy/tree/master
13
+ EXEMPLARS_TEST_DIR = File.join("test", "exemplars")
14
+ EXEMPLARS_SPEC_DIR = File.join("spec", "exemplars")
15
+ # Machinist http://github.com/notahat/machinist
16
+ BLUEPRINTS_DIR = File.join("test", "blueprints")
17
+ # Factory Girl http://github.com/thoughtbot/factory_girl
18
+ FACTORY_GIRL_DIR = File.join("test", "factories")
19
+
20
+ def model_dir
21
+ @model_dir || "app/models"
22
+ end
23
+
24
+ def model_dir=(dir)
25
+ @model_dir = dir
26
+ end
27
+
28
+ # Simple quoting for the default column value
29
+ def quote(value)
30
+ case value
31
+ when NilClass then "NULL"
32
+ when TrueClass then "TRUE"
33
+ when FalseClass then "FALSE"
34
+ when Float, Fixnum, Bignum then value.to_s
35
+ # BigDecimals need to be output in a non-normalized form and quoted.
36
+ when BigDecimal then value.to_s('F')
37
+ else
38
+ value.inspect
39
+ end
40
+ end
41
+
42
+ # Use the column information in an ActiveRecord class
43
+ # to create a comment block containing a line for
44
+ # each column. The line contains the column name,
45
+ # the type (and length), and any optional attributes
46
+ def get_schema_info(klass, header, options = {})
47
+ info = "# #{header}\n#\n"
48
+ info << "# Table name: #{klass.table_name}\n#\n"
49
+
50
+ max_size = klass.column_names.collect{|name| name.size}.max + 1
51
+ klass.columns.each do |col|
52
+ attrs = []
53
+ attrs << "default(#{quote(col.default)})" unless col.default.nil?
54
+ attrs << "not null" unless col.null
55
+ attrs << "primary key" if col.name == klass.primary_key
56
+
57
+ col_type = col.type.to_s
58
+ if col_type == "decimal"
59
+ col_type << "(#{col.precision}, #{col.scale})"
60
+ else
61
+ col_type << "(#{col.limit})" if col.limit
62
+ end
63
+
64
+ # Check out if we got a geometric column
65
+ # and print the type and SRID
66
+ if col.respond_to?(:geometry_type)
67
+ attrs << "#{col.geometry_type}, #{col.srid}"
68
+ end
69
+
70
+ # Check if the column has indices and print "indexed" if true
71
+ # If the indice include another colum, print it too.
72
+ if options[:simple_indexes] # Check out if this column is indexed
73
+ indices = klass.connection.indexes(klass.table_name)
74
+ if indices = indices.select { |ind| ind.columns.include? col.name }
75
+ indices.each do |ind|
76
+ ind = ind.columns.reject! { |i| i == col.name }
77
+ attrs << (ind.length == 0 ? "indexed" : "indexed => [#{ind.join(", ")}]")
78
+ end
79
+ end
80
+ end
81
+
82
+ info << sprintf("# %-#{max_size}.#{max_size}s:%-15.15s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n"
83
+ end
84
+
85
+ if options[:show_indexes]
86
+ info << get_index_info(klass)
87
+ end
88
+
89
+ info << "#\n\n"
90
+ end
91
+
92
+ def get_index_info(klass)
93
+ index_info = "#\n# Indexes\n#\n"
94
+
95
+ indexes = klass.connection.indexes(klass.table_name)
96
+ return "" if indexes.empty?
97
+
98
+ max_size = indexes.collect{|index| index.name.size}.max + 1
99
+ indexes.each do |index|
100
+ index_info << sprintf("# %-#{max_size}.#{max_size}s %s %s", index.name, "(#{index.columns.join(",")})", index.unique ? "UNIQUE" : "").rstrip + "\n"
101
+ end
102
+ return index_info
103
+ end
104
+
105
+ # Add a schema block to a file. If the file already contains
106
+ # a schema info block (a comment starting with "== Schema Information"), check if it
107
+ # matches the block that is already there. If so, leave it be. If not, remove the old
108
+ # info block and write a new one.
109
+ # Returns true or false depending on whether the file was modified.
110
+ #
111
+ # === Options (opts)
112
+ # :position<Symbol>:: where to place the annotated section in fixture or model file,
113
+ # "before" or "after". Default is "before".
114
+ # :position_in_class<Symbol>:: where to place the annotated section in model file
115
+ # :position_in_fixture<Symbol>:: where to place the annotated section in fixture file
116
+ # :position_in_others<Symbol>:: where to place the annotated section in the rest of
117
+ # supported files
118
+ #
119
+ def annotate_one_file(file_name, info_block, options={})
120
+ if File.exist?(file_name)
121
+ old_content = File.read(file_name)
122
+
123
+ # Ignore the Schema version line because it changes with each migration
124
+ header = Regexp.new(/(^# Table name:.*?\n(#.*\n)*\n)/)
125
+ old_header = old_content.match(header).to_s
126
+ new_header = info_block.match(header).to_s
127
+
128
+ if old_header == new_header
129
+ false
130
+ else
131
+ # Remove old schema info
132
+ old_content.sub!(/^\n?# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n/, '')
133
+
134
+ # Write it back
135
+ new_content = options[:position] == 'before' ? (info_block + old_content) : (old_content + "\n" + info_block)
136
+
137
+ File.open(file_name, "wb") { |f| f.puts new_content }
138
+ true
139
+ end
140
+ end
141
+ end
142
+
143
+ def remove_annotation_of_file(file_name)
144
+ if File.exist?(file_name)
145
+ content = File.read(file_name)
146
+
147
+ content.sub!(/^\n?# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n/, '')
148
+
149
+ File.open(file_name, "wb") { |f| f.puts content }
150
+ end
151
+ end
152
+
153
+ # Given the name of an ActiveRecord class, create a schema
154
+ # info block (basically a comment containing information
155
+ # on the columns and their types) and put it at the front
156
+ # of the model and fixture source files.
157
+ # Returns true or false depending on whether the source
158
+ # files were modified.
159
+ def annotate(klass, file, header,options={})
160
+ info = get_schema_info(klass, header, options)
161
+ annotated = false
162
+ model_name = klass.name.underscore
163
+ model_file_name = File.join(model_dir, file)
164
+
165
+ if annotate_one_file(model_file_name, info, options_with_position(options, :position_in_class))
166
+ annotated = true
167
+ end
168
+
169
+ unless ENV['exclude_tests']
170
+ [
171
+ File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"), # test
172
+ File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"), # spec
173
+ ].each do |file|
174
+ # todo: add an option "position_in_test" -- or maybe just ask if anyone ever wants different positions for model vs. test vs. fixture
175
+ annotate_one_file(file, info, options_with_position(options, :position_in_fixture))
176
+ end
177
+ end
178
+
179
+ unless ENV['exclude_fixtures']
180
+ [
181
+ File.join(EXEMPLARS_TEST_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
182
+ File.join(EXEMPLARS_SPEC_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
183
+ File.join(BLUEPRINTS_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
184
+ File.join(FACTORY_GIRL_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
185
+ ].each do |file|
186
+ annotate_one_file(file, info, options_with_position(options, :position_in_fixture))
187
+ end
188
+
189
+ FIXTURE_DIRS.each do |dir|
190
+ fixture_file_name = File.join(dir,klass.table_name + ".yml")
191
+ if File.exist?(fixture_file_name)
192
+ annotate_one_file(fixture_file_name, info, options_with_position(options, :position_in_fixture))
193
+ end
194
+ end
195
+ end
196
+
197
+ annotated
198
+ end
199
+
200
+ # position = :position_in_fixture or :position_in_class
201
+ def options_with_position(options, position_in)
202
+ options.merge(:position=>(options[position_in] || options[:position]))
203
+ end
204
+
205
+ # Return a list of the model files to annotate. If we have
206
+ # command line arguments, they're assumed to be either
207
+ # the underscore or CamelCase versions of model names.
208
+ # Otherwise we take all the model files in the
209
+ # model_dir directory.
210
+ def get_model_files
211
+ models = ARGV.dup
212
+ models.shift
213
+ models.reject!{|m| m.match(/^(.*)=/)}
214
+ if models.empty?
215
+ begin
216
+ Dir.chdir(model_dir) do
217
+ models = Dir["**/*.rb"]
218
+ end
219
+ rescue SystemCallError
220
+ puts "No models found in directory '#{model_dir}'."
221
+ puts "Either specify models on the command line, or use the --model-dir option."
222
+ puts "Call 'annotate --help' for more info."
223
+ exit 1;
224
+ end
225
+ end
226
+ models
227
+ end
228
+
229
+ # Retrieve the classes belonging to the model names we're asked to process
230
+ # Check for namespaced models in subdirectories as well as models
231
+ # in subdirectories without namespacing.
232
+ def get_model_class(file)
233
+ require File.expand_path("#{model_dir}/#{file}") # this is for non-rails projects, which don't get Rails auto-require magic
234
+ model = file.gsub(/\.rb$/, '').camelize
235
+ parts = model.split('::')
236
+ begin
237
+ parts.inject(Object) {|klass, part| klass.const_get(part) }
238
+ rescue LoadError, NameError
239
+ Object.const_get(parts.last)
240
+ end
241
+ end
242
+
243
+ # We're passed a name of things that might be
244
+ # ActiveRecord models. If we can find the class, and
245
+ # if its a subclass of ActiveRecord::Base,
246
+ # then pass it to the associated block
247
+ def do_annotations(options={})
248
+ if options[:require]
249
+ options[:require].each do |path|
250
+ require path
251
+ end
252
+ end
253
+
254
+ header = PREFIX.dup
255
+
256
+ if options[:include_version]
257
+ version = ActiveRecord::Migrator.current_version rescue 0
258
+ if version > 0
259
+ header << "\n# Schema version: #{version}"
260
+ end
261
+ end
262
+
263
+ if options[:model_dir]
264
+ self.model_dir = options[:model_dir]
265
+ end
266
+
267
+ annotated = []
268
+ get_model_files.each do |file|
269
+ begin
270
+ klass = get_model_class(file)
271
+ if klass < ActiveRecord::Base && !klass.abstract_class?
272
+ if annotate(klass, file, header, options)
273
+ annotated << klass
274
+ end
275
+ end
276
+ rescue Exception => e
277
+ puts "Unable to annotate #{file}: #{e.inspect}"
278
+ puts ""
279
+ # todo: check if all backtrace lines are in "gems" -- if so, it's an annotate bug, so print the whole stack trace.
280
+ # puts e.backtrace.join("\n\t")
281
+ end
282
+ end
283
+ if annotated.empty?
284
+ puts "Nothing annotated."
285
+ else
286
+ puts "Annotated (#{annotated.length}): #{annotated.join(', ')}"
287
+ end
288
+ end
289
+
290
+ def remove_annotations(options={})
291
+ if options[:model_dir]
292
+ puts "removing"
293
+ self.model_dir = options[:model_dir]
294
+ end
295
+ deannotated = []
296
+ get_model_files.each do |file|
297
+ begin
298
+ klass = get_model_class(file)
299
+ if klass < ActiveRecord::Base && !klass.abstract_class?
300
+ deannotated << klass
301
+
302
+ model_file_name = File.join(model_dir, file)
303
+ remove_annotation_of_file(model_file_name)
304
+
305
+ FIXTURE_DIRS.each do |dir|
306
+ fixture_file_name = File.join(dir,klass.table_name + ".yml")
307
+ remove_annotation_of_file(fixture_file_name) if File.exist?(fixture_file_name)
308
+ end
309
+
310
+ [ File.join(UNIT_TEST_DIR, "#{klass.name.underscore}_test.rb"),
311
+ File.join(SPEC_MODEL_DIR,"#{klass.name.underscore}_spec.rb")].each do |file|
312
+ remove_annotation_of_file(file) if File.exist?(file)
313
+ end
314
+
315
+ end
316
+ rescue Exception => e
317
+ puts "Unable to annotate #{file}: #{e.message}"
318
+ end
319
+ end
320
+ puts "Removed annotation from: #{deannotated.join(', ')}"
321
+ end
322
+ end
323
+ end
324
+
325
+ # monkey patches
326
+
327
+ module ::ActiveRecord
328
+ class Base
329
+ def self.method_missing(name, *args)
330
+ # ignore this, so unknown/unloaded macros won't cause parsing to fail
331
+ end
332
+ end
333
+ end
@@ -0,0 +1,41 @@
1
+ # == Annotate Routes
2
+ #
3
+ # Based on:
4
+ #
5
+ #
6
+ #
7
+ # Prepends the output of "rake routes" to the top of your routes.rb file.
8
+ # Yes, it's simple but I'm thick and often need a reminder of what my routes mean.
9
+ #
10
+ # Running this task will replace any exising route comment generated by the task.
11
+ # Best to back up your routes file before running:
12
+ #
13
+ # Author:
14
+ # Gavin Montague
15
+ # gavin@leftbrained.co.uk
16
+ #
17
+ # Released under the same license as Ruby. No Support. No Warranty.module AnnotateRoutes
18
+ #
19
+ module AnnotateRoutes
20
+ PREFIX = "#== Route Map"
21
+
22
+ def self.do_annotate
23
+ routes_rb = File.join("config", "routes.rb")
24
+ header = PREFIX + "\n# Generated on #{Time.now.strftime("%d %b %Y %H:%M")}\n#"
25
+ if File.exists? routes_rb
26
+ routes_map = `rake routes`
27
+ routes_map = routes_map.split("\n")
28
+ routes_map.shift # remove the first line of rake routes which is just a file path
29
+ routes_map = routes_map.inject(header){|sum, line| sum<<"\n# "<<line}
30
+ content = File.read(routes_rb)
31
+ content, old = content.split(/^#== Route .*?\n/)
32
+ File.open(routes_rb, "wb") do |f|
33
+ f.puts content.sub!(/\n?\z/, "\n") + routes_map
34
+ end
35
+ puts "Route file annotated."
36
+ else
37
+ puts "Can`t find routes.rb"
38
+ end
39
+ end
40
+
41
+ end
data/lib/annotate.rb ADDED
@@ -0,0 +1,24 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module Annotate
5
+ def self.version
6
+ version_file = File.dirname(__FILE__) + "/../VERSION.yml"
7
+ if File.exist?(version_file)
8
+ config = YAML.load(File.read(version_file))
9
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
10
+ else
11
+ version = "0.0.0"
12
+ end
13
+ end
14
+
15
+ def self.load_tasks
16
+ if File.exists?('Rakefile')
17
+ load 'Rakefile'
18
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |rake| load rake }
19
+ return true
20
+ else
21
+ return false
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ desc "Add schema information (as comments) to model and fixture files"
2
+ task :annotate_models => :environment do
3
+ require 'annotate/annotate_models'
4
+ options={}
5
+ options[:position_in_class] = ENV['position_in_class'] || ENV['position'] || :before
6
+ options[:position_in_fixture] = ENV['position_in_fixture'] || ENV['position'] || :before
7
+ options[:show_indexes] = ENV['show_indexes']
8
+ options[:simple_indexes] = ENV['simple_indexes']
9
+ options[:model_dir] = ENV['model_dir']
10
+ options[:include_version] = ENV['include_version']
11
+ options[:require] = ENV['require'] ? ENV['require'].split(',') : []
12
+ AnnotateModels.do_annotations(options)
13
+ end
14
+
15
+ desc "Remove schema information from model and fixture files"
16
+ task :remove_annotation => :environment do
17
+ require 'annotate/annotate_models'
18
+ options={}
19
+ options[:model_dir] = ENV['model_dir']
20
+ AnnotateModels.remove_annotations(options)
21
+ end
@@ -0,0 +1,5 @@
1
+ desc "Prepends the route map to the top of routes.rb"
2
+ task :annotate_routes do
3
+ require 'annotate/annotate_routes'
4
+ AnnotateRoutes.do_annotate
5
+ end
@@ -0,0 +1,141 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require 'annotate/annotate_models'
3
+ require 'rubygems'
4
+ require 'activesupport'
5
+
6
+ describe AnnotateModels do
7
+
8
+ def mock_klass(stubs={})
9
+ @mock_file ||= mock("Klass", stubs)
10
+ end
11
+
12
+ def mock_column(stubs={})
13
+ @mock_column ||= mock("Column", stubs)
14
+ end
15
+
16
+ it { AnnotateModels.quote(nil).should eql("NULL") }
17
+ it { AnnotateModels.quote(true).should eql("TRUE") }
18
+ it { AnnotateModels.quote(false).should eql("FALSE") }
19
+ it { AnnotateModels.quote(25).should eql("25") }
20
+ it { AnnotateModels.quote(25.6).should eql("25.6") }
21
+ it { AnnotateModels.quote(1e-20).should eql("1.0e-20") }
22
+
23
+ it "should get schema info" do
24
+
25
+ AnnotateModels.get_schema_info(mock_klass(
26
+ :connection => mock("Conn", :indexes => []),
27
+ :table_name => "users",
28
+ :primary_key => "id",
29
+ :column_names => ["id","login"],
30
+ :columns => [
31
+ mock_column(:type => "integer", :default => nil, :null => false, :name => "id", :limit => nil),
32
+ mock_column(:type => "string", :default => nil, :null => false, :name => "name", :limit => 50)
33
+ ]), "Schema Info").should eql(<<-EOS)
34
+ # Schema Info
35
+ #
36
+ # Table name: users
37
+ #
38
+ # id :integer not null, primary key
39
+ # id :integer not null, primary key
40
+ #
41
+
42
+ EOS
43
+
44
+ end
45
+
46
+ describe "#get_model_class" do
47
+ module ::ActiveRecord
48
+ class Base
49
+ end
50
+ end
51
+
52
+ def create(file, body="hi")
53
+ File.open(@dir + '/' + file, "w") do |f|
54
+ f.puts(body)
55
+ end
56
+ end
57
+
58
+ before :all do
59
+ require "tmpdir"
60
+ @dir = Dir.tmpdir + "/#{Time.now.to_i}" + "/annotate_models"
61
+ FileUtils.mkdir_p(@dir)
62
+ AnnotateModels.model_dir = @dir
63
+ create('foo.rb', <<-EOS)
64
+ class Foo < ActiveRecord::Base
65
+ end
66
+ EOS
67
+ create('foo_with_macro.rb', <<-EOS)
68
+ class FooWithMacro < ActiveRecord::Base
69
+ acts_as_awesome :yah
70
+ end
71
+ EOS
72
+ end
73
+ it "should work" do
74
+ klass = AnnotateModels.get_model_class("foo.rb")
75
+ klass.name.should == "Foo"
76
+ end
77
+ it "should not care about unknown macros" do
78
+ klass = AnnotateModels.get_model_class("foo_with_macro.rb")
79
+ klass.name.should == "FooWithMacro"
80
+ end
81
+ end
82
+
83
+ describe "#remove_annotation_of_file" do
84
+ def create(file, body="hi")
85
+ File.open(@dir + '/' + file, "w") do |f|
86
+ f.puts(body)
87
+ end
88
+ end
89
+ def content(file)
90
+ File.read(@dir + '/' + file)
91
+ end
92
+
93
+ before :all do
94
+ require "tmpdir"
95
+ @dir = Dir.tmpdir + "/#{Time.now.to_i}" + "/annotate_models"
96
+ FileUtils.mkdir_p(@dir)
97
+ create("before.rb", <<-EOS)
98
+ # == Schema Information
99
+ #
100
+ # Table name: foo
101
+ #
102
+ # id :integer not null, primary key
103
+ # created_at :datetime
104
+ # updated_at :datetime
105
+ #
106
+
107
+ class Foo < ActiveRecord::Base
108
+ end
109
+ EOS
110
+ create("after.rb", <<-EOS)
111
+ class Foo < ActiveRecord::Base
112
+ end
113
+
114
+ # == Schema Information
115
+ #
116
+ # Table name: foo
117
+ #
118
+ # id :integer not null, primary key
119
+ # created_at :datetime
120
+ # updated_at :datetime
121
+ #
122
+
123
+ EOS
124
+ end
125
+ it "should remove before annotate" do
126
+ AnnotateModels.remove_annotation_of_file(@dir + '/' + "before.rb")
127
+ content("before.rb").should == <<-EOS
128
+ class Foo < ActiveRecord::Base
129
+ end
130
+ EOS
131
+ end
132
+ it "should remove after annotate" do
133
+ AnnotateModels.remove_annotation_of_file(@dir + '/' + "after.rb")
134
+ content("after.rb").should == <<-EOS
135
+ class Foo < ActiveRecord::Base
136
+ end
137
+ EOS
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require 'annotate/annotate_routes'
3
+
4
+ describe AnnotateRoutes do
5
+
6
+ def mock_file(stubs={})
7
+ @mock_file ||= mock(File, stubs)
8
+ end
9
+
10
+ describe "Annotate Job" do
11
+
12
+ before(:each) do
13
+ File.should_receive(:join).with("config", "routes.rb").and_return("config/routes.rb")
14
+ end
15
+
16
+ it "should check if routes.rb exists" do
17
+ File.should_receive(:exists?).with("config/routes.rb").and_return(false)
18
+ AnnotateRoutes.should_receive(:puts).with("Can`t find routes.rb")
19
+ AnnotateRoutes.do_annotate
20
+ end
21
+
22
+ describe "When Annotating" do
23
+
24
+ before(:each) do
25
+ File.should_receive(:exists?).with("config/routes.rb").and_return(true)
26
+ AnnotateRoutes.should_receive(:`).with("rake routes").and_return("bad line\ngood line")
27
+ File.should_receive(:open).with("config/routes.rb", "wb").and_yield(mock_file)
28
+ AnnotateRoutes.should_receive(:puts).with("Route file annotated.")
29
+ end
30
+
31
+ it "should annotate and add a newline!" do
32
+ File.should_receive(:read).with("config/routes.rb").and_return("ActionController::Routing...\nfoo")
33
+ @mock_file.should_receive(:puts).with(/ActionController::Routing...\nfoo\n#== Route Map\n# Generated on .*\n#\n# good line/)
34
+ AnnotateRoutes.do_annotate
35
+ end
36
+
37
+ it "should not add a newline if there are empty lines" do
38
+ File.should_receive(:read).with("config/routes.rb").and_return("ActionController::Routing...\nfoo\n")
39
+ @mock_file.should_receive(:puts).with(/ActionController::Routing...\nfoo\n#== Route Map\n# Generated on .*\n#\n# good line/)
40
+ AnnotateRoutes.do_annotate
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Annotate do
4
+
5
+ it "should have a version" do
6
+ Annotate.version.should be_instance_of(String)
7
+ end
8
+
9
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'annotate'
@@ -0,0 +1,33 @@
1
+ # These tasks are added to the project if you install annotate as a Rails plugin.
2
+ # (They are not used to build annotate itself.)
3
+
4
+ # Append annotations to Rake tasks for ActiveRecord, so annotate automatically gets
5
+ # run after doing db:migrate.
6
+ # Unfortunately it relies on ENV for options; it'd be nice to be able to set options
7
+ # in a per-project config file so this task can read them.
8
+ namespace :db do
9
+ task :migrate do
10
+ Annotate::Migration.update_annotations
11
+ end
12
+
13
+ namespace :migrate do
14
+ [:up, :down, :reset, :redo].each do |t|
15
+ task t do
16
+ Annotate::Migration.update_annotations
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module Annotate
23
+ class Migration
24
+ @@working = false
25
+
26
+ def self.update_annotations
27
+ unless @@working
28
+ @@working = true
29
+ Rake::Task['annotate_models'].invoke
30
+ end
31
+ end
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: netsign-annotate
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 2
8
+ - 4
9
+ - 4
10
+ version: 2.4.4
11
+ platform: ruby
12
+ authors:
13
+ - Cuong Tran
14
+ - Alex Chaffee
15
+ - Marcos Piccinini
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2011-01-30 00:00:00 -08:00
21
+ default_executable: annotate
22
+ dependencies: []
23
+
24
+ description: Packaged for netSIGN, gem experimentation
25
+ email:
26
+ - alex@stinky.com
27
+ - ctran@pragmaquest.com
28
+ - x@nofxx.com
29
+ executables:
30
+ - annotate
31
+ extensions: []
32
+
33
+ extra_rdoc_files:
34
+ - README.rdoc
35
+ files:
36
+ - History.txt
37
+ - README.rdoc
38
+ - VERSION.yml
39
+ - bin/annotate
40
+ - lib/annotate.rb
41
+ - lib/annotate/annotate_models.rb
42
+ - lib/annotate/annotate_routes.rb
43
+ - lib/tasks/annotate_models.rake
44
+ - lib/tasks/annotate_routes.rake
45
+ - spec/annotate/annotate_models_spec.rb
46
+ - spec/annotate/annotate_routes_spec.rb
47
+ - spec/annotate_spec.rb
48
+ - spec/spec.opts
49
+ - spec/spec_helper.rb
50
+ - tasks/migrate.rake
51
+ has_rdoc: true
52
+ homepage: https://github.com/miyucy/annotate_models
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project: netsign-annotate
81
+ rubygems_version: 1.3.7
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Annotates Rails Models, routes, fixtures, and others based on the database schema.
85
+ test_files:
86
+ - spec/annotate/annotate_models_spec.rb
87
+ - spec/annotate/annotate_routes_spec.rb
88
+ - spec/annotate_spec.rb
89
+ - spec/spec_helper.rb