selleo-annotate 2.3.2

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/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .DS_Store
2
+ doc/*
3
+ rdoc/*
4
+ coverage/*
5
+ spec/debug.log
6
+ pkg/*
7
+ .idea
8
+ .idea/**/*
data/History.txt ADDED
@@ -0,0 +1,27 @@
1
+ == 2.0 2009-02-03
2
+
3
+ * Add annotate_models plugin fork additions
4
+ * Annotates Rspec and Test Unit models
5
+ * Annotates Object Daddy exemplars
6
+ * Annotates geometrical columns
7
+ * Add AnnotateRoutes rake task
8
+ * Up gem structure to newgem defaults
9
+
10
+ == 1.0.4 2008-09-04
11
+
12
+ * Only update modified models since last run, thanks to sant0sk1
13
+
14
+ == 1.0.3 2008-05-02
15
+
16
+ * Add misc changes from Dustin Sallings and Henrik N
17
+ * Remove trailing whitespace
18
+ * More intuitive info messages
19
+ * Update README file with update-to-date example
20
+
21
+ == 1.0.2 2008-03-22
22
+
23
+ * Add contributions from Michael Bumann (http://github.com/bumi)
24
+ * added an option "position" to choose to put the annotation,
25
+ * spec/fixtures now also get annotated
26
+ * added a task to remove the annotations
27
+ * these options can be specified from command line as -d and -p [before|after]
data/README.rdoc ADDED
@@ -0,0 +1,166 @@
1
+ _
2
+ /_| _/__/_
3
+ ( |/)/)()/(//(-
4
+ ________________
5
+
6
+
7
+ Add a comment summarizing the current schema to the bottom of each
8
+ ActiveRecord model, fixture file.
9
+
10
+ If you are using Object Daddy, it`ll annotate your example files too.
11
+
12
+ # == Schema Info
13
+ #
14
+ # Table name: line_items
15
+ #
16
+ # id :integer(11) not null, primary key
17
+ # quantity :integer(11) not null
18
+ # product_id :integer(11) not null
19
+ # unit_price :float
20
+ # order_id :integer(11)
21
+ #
22
+
23
+ class LineItem < ActiveRecord::Base
24
+ belongs_to :product
25
+ . . .
26
+
27
+ Annotates geometrical columns, geom type and srid, when using SpatialAdapter or PostgisAdapter:
28
+
29
+ # == Schema Info
30
+ #
31
+ # Table name: trips
32
+ #
33
+ # local :geometry point, 4326
34
+ # path :geometry line_string, 4326
35
+
36
+
37
+ == INSTALL
38
+
39
+ sudo gem install nofxx-annotate
40
+
41
+
42
+ == HOW TO USE:
43
+ =======
44
+ == Warning
45
+
46
+ Note that this code will blow away the initial/final comment
47
+ block in your models if it looks like it was previously added
48
+ by annotate models, so you don't want to add additional text
49
+ to an automatically created comment block.
50
+
51
+ * * Back up your model files before using... * *
52
+
53
+ == Install
54
+
55
+ From rubyforge:
56
+
57
+ sudo gem install annotate
58
+
59
+ From github:
60
+
61
+ gem sources -a http://gems.github.com
62
+ sudo gem install ctran-annotate
63
+
64
+ == Usage
65
+
66
+ To annotate all your models:
67
+
68
+ cd /path/to/app
69
+ annotate
70
+
71
+ To annotate routes.rb:
72
+
73
+ annotate -r
74
+
75
+ More:
76
+
77
+ annotate -h
78
+
79
+
80
+ To migrate & annotate (TODO):
81
+
82
+
83
+ Options:
84
+
85
+ Annotate on the head of the file:
86
+
87
+ annotate -p [before|after]
88
+
89
+
90
+ == WARNING
91
+
92
+ Note that this code will blow away the initial/final comment
93
+ block in your models if it looks like it was previously added
94
+ by annotate models, so you don't want to add additional text
95
+ to an automatically created comment block.
96
+
97
+ * * Back up your model files before using... * *
98
+
99
+ == LINKS
100
+
101
+ * Factory Girl => http://github.com/thoughtbot/factory_girl (NOT IMPLEMENTED)
102
+ * Object Daddy => http://github.com/flogic/object_daddy
103
+
104
+ * SpatialAdapter => http://github.com/pdeffendol/spatial_adapter
105
+ * PostgisAdapter => http://github.com/nofxx/postgis_adapter
106
+
107
+
108
+ == TODO
109
+
110
+ * Spec
111
+
112
+
113
+ == LICENSE:
114
+ =======
115
+ More options:
116
+
117
+ Usage: annotate [options]
118
+ -d, --delete Remove annotations from all model files
119
+ -p, --position [before|after] Place the annotations at the top (before) or the bottom (after) of the model file
120
+ -r, --routes Annotate routes.rb with the output of 'rake routes'
121
+ -v, --version Show the current version of this gem
122
+ -m, --show-migration Include the migration version number in the annotation
123
+ -i, --show-indexes List the table's database indexes in the annotation
124
+ --model-dir dir Annotate model files stored in dir rather than app/models
125
+
126
+ == LICENSE:
127
+
128
+ Released under the same license as Ruby. No Support. No Warranty.
129
+
130
+ == Author:
131
+
132
+ Original code by:
133
+
134
+ Dave Thomas -- Pragmatic Programmers, LLC
135
+
136
+ AnnotateModels mods by:
137
+
138
+ Alexander Semyonov ( http://github.com/rotuka/annotate_models )
139
+
140
+ AnnotateRoutes originally by:
141
+
142
+ Gavin Montague ( http://github.com/govan/annotate-routes )
143
+
144
+
145
+ == Forked from:
146
+
147
+ http://github.com/ctran/annotate_models
148
+
149
+
150
+ == Modifications
151
+ - alex@pivotallabs.com
152
+ =======
153
+ Modifications by:
154
+
155
+ - Alex Chaffee - http://github.com/alexch - alex@pivotallabs.com
156
+ - Cuong Tran - http://github.com/ctran
157
+ - Jack Danger - http://github.com/JackDanger
158
+ - Michael Bumann - http://github.com/bumi
159
+ - Henrik Nyh - http://github.com/henrik
160
+ - Marcos Piccinini - http://github.com/nofxx
161
+
162
+ and many others that I may have missed to add.
163
+
164
+ == This fork
165
+
166
+ Marcos Piccinini ( http://github.com/nofxx/annotate )
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "selleo-annotate"
8
+ gem.summary = "Annotates Rails Models, routes, automatic annotation and others"
9
+ gem.email = "x@selleo.com"
10
+ gem.homepage = "http://github.com/selleo/annotate"
11
+ gem.authors = ['Cuong Tran',"Marcos Piccinini"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'spec/rake/spectask'
20
+ Spec::Rake::SpecTask.new(:spec) do |spec|
21
+ spec.libs << 'lib' << 'spec'
22
+ spec.spec_files = FileList['spec/**/*_spec.rb']
23
+ end
24
+
25
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
26
+ spec.libs << 'lib' << 'spec'
27
+ spec.pattern = 'spec/**/*_spec.rb'
28
+ spec.rcov = true
29
+ end
30
+
31
+
32
+ task :default => :spec
33
+
34
+ require 'rake/rdoctask'
35
+ Rake::RDocTask.new do |rdoc|
36
+ if File.exist?('VERSION.yml')
37
+ config = YAML.load(File.read('VERSION.yml'))
38
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
39
+ else
40
+ version = ""
41
+ end
42
+
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = "annotate #{version}"
45
+ rdoc.rdoc_files.include('README*')
46
+ rdoc.rdoc_files.include('lib/**/*.rb')
47
+ end
48
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.3.2
data/bin/annotate ADDED
@@ -0,0 +1,64 @@
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]"
10
+ opts.on('-d', '--delete',
11
+ "Remove annotations from all model files") do
12
+ task = :remove_annotation
13
+ end
14
+ opts.on('-p', '--position [before|after]', ['before', 'after'],
15
+ "Place the annotations at the top (before) or the bottom (after) of the model file") do |p|
16
+ ENV['position'] = p
17
+ end
18
+ opts.on('-r', '--routes',
19
+ "Annotate routes.rb with the output of 'rake routes'") do
20
+ task = :annotate_routes
21
+ end
22
+ opts.on('-A', '--automatic_annotate',
23
+ "Annotate each time when server boots in development mode") do
24
+ task = :automatic_annotate
25
+ end
26
+ opts.on('-D', '--remove_automatic_annotation',
27
+ "Remove automatic annotate when server boots") do
28
+ task = :remove_automatic_annotation
29
+ end
30
+ opts.on('-v', '--version',
31
+ "Show the current version of this gem") do
32
+ puts "Annotate v#{Annotate::VERSION}"; exit
33
+ end
34
+ opts.on('-m', '--show-migration',
35
+ "Include the migration version number in the annotation") do
36
+ ENV['include_version'] = "yes"
37
+ end
38
+ opts.on('-i', '--show-indexes',
39
+ "List the table's database indexes in the annotation") do
40
+ ENV['show_indexes'] = "yes"
41
+ end
42
+ opts.on('-s', '--simple-indexes',
43
+ "Concat the column's related indexes in the annotation") do
44
+ ENV['simple_indexes'] = "yes"
45
+ end
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
+ opts.on('-R', '--require path',
51
+ "Additional files to require before loading models") do |path|
52
+ if ENV['require']
53
+ ENV['require'] = ENV['require'] + ",#{path}"
54
+ else
55
+ ENV['require'] = path
56
+ end
57
+ end
58
+ end.parse!
59
+
60
+ if Annotate.load_tasks
61
+ Rake::Task[task].invoke
62
+ else
63
+ STDERR.puts "Can't find Rakefile. Are we in a Rails folder?"
64
+ end
data/lib/annotate.rb ADDED
@@ -0,0 +1,14 @@
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.load_tasks
6
+ if File.exists?('Rakefile')
7
+ load 'Rakefile'
8
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |rake| load rake }
9
+ return true
10
+ else
11
+ return false
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,293 @@
1
+ module AnnotateModels
2
+ class << self
3
+ # Annotate Models plugin use this header
4
+ COMPAT_PREFIX = "== Schema Info"
5
+ PREFIX = "== Schema Information"
6
+ FIXTURE_DIRS = ["test/fixtures","spec/fixtures"]
7
+ # File.join for windows reverse bar compat?
8
+ # I dont use windows, can`t test
9
+ UNIT_TEST_DIR = File.join("test", "unit" )
10
+ SPEC_MODEL_DIR = File.join("spec", "models")
11
+ EXEMPLARS_TEST_DIR = File.join("test", "exemplars")
12
+ # Object Daddy http://github.com/flogic/object_daddy/tree/master
13
+ EXEMPLARS_SPEC_DIR = File.join("spec", "exemplars")
14
+ # Machinist http://github.com/notahat/machinist
15
+ BLUEPRINTS_DIR = File.join("test", "blueprints")
16
+
17
+ def model_dir
18
+ @model_dir || "app/models"
19
+ end
20
+
21
+ def model_dir=(dir)
22
+ @model_dir = dir
23
+ end
24
+
25
+ # Simple quoting for the default column value
26
+ def quote(value)
27
+ case value
28
+ when NilClass then "NULL"
29
+ when TrueClass then "TRUE"
30
+ when FalseClass then "FALSE"
31
+ when Float, Fixnum, Bignum then value.to_s
32
+ # BigDecimals need to be output in a non-normalized form and quoted.
33
+ when BigDecimal then value.to_s('F')
34
+ else
35
+ value.inspect
36
+ end
37
+ end
38
+
39
+ # Use the column information in an ActiveRecord class
40
+ # to create a comment block containing a line for
41
+ # each column. The line contains the column name,
42
+ # the type (and length), and any optional attributes
43
+ def get_schema_info(klass, header, options = {})
44
+ info = "# #{header}\n#\n"
45
+ info << "# Table name: #{klass.table_name}\n#\n"
46
+
47
+ max_size = klass.column_names.collect{|name| name.size}.max + 1
48
+ klass.columns.each do |col|
49
+ attrs = []
50
+ attrs << "default(#{quote(col.default)})" unless col.default.nil?
51
+ attrs << "not null" unless col.null
52
+ attrs << "primary key" if col.name == klass.primary_key
53
+
54
+ col_type = col.type.to_s
55
+ if col_type == "decimal"
56
+ col_type << "(#{col.precision}, #{col.scale})"
57
+ else
58
+ col_type << "(#{col.limit})" if col.limit
59
+ end
60
+
61
+ # Check out if we got a geometric column
62
+ # and print the type and SRID
63
+ if col.respond_to?(:geometry_type)
64
+ attrs << "#{col.geometry_type}, #{col.srid}"
65
+ end
66
+
67
+ # Check if the column has indices and print "indexed" if true
68
+ # If the indice include another colum, print it too.
69
+ if options[:simple_indexes] # Check out if this column is indexed
70
+ indices = klass.connection.indexes(klass.table_name)
71
+ if indices = indices.select { |ind| ind.columns.include? col.name }
72
+ indices.each do |ind|
73
+ ind = ind.columns.reject! { |i| i == col.name }
74
+ attrs << (ind.length == 0 ? "indexed" : "indexed => [#{ind.join(", ")}]")
75
+ end
76
+ end
77
+ end
78
+ info << sprintf("# %-#{max_size}.#{max_size}s:%-15.15s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n"
79
+ end
80
+
81
+ if options[:show_indexes]
82
+ info << get_index_info(klass)
83
+ end
84
+
85
+ info << "#\n\n"
86
+ end
87
+
88
+ def get_index_info(klass)
89
+ index_info = "#\n# Indexes\n#\n"
90
+
91
+ indexes = klass.connection.indexes(klass.table_name)
92
+ return "" if indexes.empty?
93
+
94
+ max_size = indexes.collect{|index| index.name.size}.max + 1
95
+ indexes.each do |index|
96
+ index_info << sprintf("# %-#{max_size}.#{max_size}s %s %s", index.name, "(#{index.columns.join(",")})", index.unique ? "UNIQUE" : "").rstrip + "\n"
97
+ end
98
+ return index_info
99
+ end
100
+
101
+ # Add a schema block to a file. If the file already contains
102
+ # a schema info block (a comment starting with "== Schema Information"), check if it
103
+ # matches the block that is already there. If so, leave it be. If not, remove the old
104
+ # info block and write a new one.
105
+ # Returns true or false depending on whether the file was modified.
106
+ #
107
+ # === Options (opts)
108
+ # :position<Symbol>:: where to place the annotated section in fixture or model file,
109
+ # "before" or "after". Default is "before".
110
+ # :position_in_class<Symbol>:: where to place the annotated section in model file
111
+ # :position_in_fixture<Symbol>:: where to place the annotated section in fixture file
112
+ # :position_in_others<Symbol>:: where to place the annotated section in the rest of
113
+ # supported files
114
+ #
115
+ def annotate_one_file(file_name, info_block, options={})
116
+ if File.exist?(file_name)
117
+ old_content = File.read(file_name)
118
+
119
+ # Ignore the Schema version line because it changes with each migration
120
+ header = Regexp.new(/(^# Table name:.*?\n(#.*\n)*\n)/)
121
+ old_header = old_content.match(header).to_s
122
+ new_header = info_block.match(header).to_s
123
+
124
+ if old_header == new_header
125
+ false
126
+ else
127
+ # Remove old schema info
128
+ old_content.sub!(/^# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n/, '')
129
+
130
+ # Write it back
131
+ new_content = options[:position] == 'before' ? (info_block + old_content) : (old_content + "\n" + info_block)
132
+
133
+ File.open(file_name, "wb") { |f| f.puts new_content }
134
+ true
135
+ end
136
+ end
137
+ end
138
+
139
+ def remove_annotation_of_file(file_name)
140
+ if File.exist?(file_name)
141
+ content = File.read(file_name)
142
+
143
+ content.sub!(/^# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n/, '')
144
+
145
+ File.open(file_name, "wb") { |f| f.puts content }
146
+ end
147
+ end
148
+
149
+ # Given the name of an ActiveRecord class, create a schema
150
+ # info block (basically a comment containing information
151
+ # on the columns and their types) and put it at the front
152
+ # of the model and fixture source files.
153
+ # Returns true or false depending on whether the source
154
+ # files were modified.
155
+
156
+ def annotate(klass, file, header,options={})
157
+ info = get_schema_info(klass, header, options)
158
+ annotated = false
159
+ model_name = klass.name.underscore
160
+ model_file_name = File.join(model_dir, file)
161
+ if annotate_one_file(model_file_name, info, options.merge(
162
+ :position=>(options[:position_in_class] || options[:position])))
163
+ annotated = true
164
+ end
165
+
166
+ [
167
+ File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"), # test
168
+ File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"), # spec
169
+ File.join(EXEMPLARS_TEST_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
170
+ File.join(EXEMPLARS_SPEC_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
171
+ File.join(BLUEPRINTS_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
172
+ ].each { |file| annotate_one_file(file, info) }
173
+
174
+ FIXTURE_DIRS.each do |dir|
175
+ fixture_file_name = File.join(dir,klass.table_name + ".yml")
176
+ annotate_one_file(fixture_file_name, info, options.merge(:position=>(options[:position_in_fixture] || options[:position]))) if File.exist?(fixture_file_name)
177
+ end
178
+ annotated
179
+ end
180
+
181
+ # Return a list of the model files to annotate. If we have
182
+ # command line arguments, they're assumed to be either
183
+ # the underscore or CamelCase versions of model names.
184
+ # Otherwise we take all the model files in the
185
+ # model_dir directory.
186
+ def get_model_files
187
+ models = ARGV.dup
188
+ models.shift
189
+ models.reject!{|m| m.starts_with?("position=")}
190
+ if models.empty?
191
+ Dir.chdir(model_dir) do
192
+ models = Dir["**/*.rb"]
193
+ end
194
+ end
195
+ models
196
+ end
197
+
198
+ # Retrieve the classes belonging to the model names we're asked to process
199
+ # Check for namespaced models in subdirectories as well as models
200
+ # in subdirectories without namespacing.
201
+ def get_model_class(file)
202
+ require File.expand_path("#{model_dir}/#{file}") # this is for non-rails projects, which don't get Rails auto-require magic
203
+ model = file.gsub(/\.rb$/, '').camelize
204
+ parts = model.split('::')
205
+ begin
206
+ parts.inject(Object) {|klass, part| klass.const_get(part) }
207
+ rescue LoadError
208
+ Object.const_get(parts.last)
209
+ end
210
+ end
211
+
212
+ # We're passed a name of things that might be
213
+ # ActiveRecord models. If we can find the class, and
214
+ # if its a subclass of ActiveRecord::Base,
215
+ # then pass it to the associated block
216
+ def do_annotations(options={})
217
+ if options[:require]
218
+ options[:require].each do |path|
219
+ require path
220
+ end
221
+ end
222
+
223
+ header = PREFIX.dup
224
+
225
+ if options[:include_version]
226
+ version = ActiveRecord::Migrator.current_version rescue 0
227
+ if version > 0
228
+ header << "\n# Schema version: #{version}"
229
+ end
230
+ end
231
+
232
+ if options[:model_dir]
233
+ self.model_dir = options[:model_dir]
234
+ end
235
+
236
+ annotated = []
237
+ get_model_files.each do |file|
238
+ begin
239
+ klass = get_model_class(file)
240
+ if klass < ActiveRecord::Base && !klass.abstract_class?
241
+ if annotate(klass, file, header,options)
242
+ annotated << klass
243
+ end
244
+ end
245
+ rescue Exception => e
246
+ puts "Unable to annotate #{file}: #{e.message} (#{e.backtrace.first})"
247
+ end
248
+ end
249
+ if annotated.empty?
250
+ puts "Nothing annotated."
251
+ else
252
+ puts "Annotated (#{annotated.length}): #{annotated.join(', ')}"
253
+ end
254
+ end
255
+
256
+ def remove_annotations(options={})
257
+ if options[:model_dir]
258
+ puts "removing"
259
+ self.model_dir = options[:model_dir]
260
+ end
261
+ deannotated = []
262
+ get_model_files.each do |file|
263
+ begin
264
+ klass = get_model_class(file)
265
+ if klass < ActiveRecord::Base && !klass.abstract_class?
266
+ deannotated << klass
267
+
268
+ model_file_name = File.join(model_dir, file)
269
+ remove_annotation_of_file(model_file_name)
270
+
271
+ FIXTURE_DIRS.each do |dir|
272
+ fixture_file_name = File.join(dir,klass.table_name + ".yml")
273
+ remove_annotation_of_file(fixture_file_name) if File.exist?(fixture_file_name)
274
+ end
275
+ end
276
+ rescue Exception => e
277
+ puts "Unable to annotate #{file}: #{e.message}"
278
+ end
279
+ end
280
+ puts "Removed annotation from: #{deannotated.join(', ')}"
281
+ end
282
+ end
283
+ end
284
+
285
+ # monkey patches
286
+
287
+ module ::ActiveRecord
288
+ class Base
289
+ def self.method_missing(name, *args)
290
+ # ignore this, so unknown/unloaded macros won't cause parsing to fail
291
+ end
292
+ end
293
+ 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
@@ -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'].split(',') rescue []
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,23 @@
1
+ RAILS_INITIALIZERS_PATH = File.join(RAILS_ROOT, "config", "initializers")
2
+
3
+ desc "Add automatic annotation to project to invoke annotate each time when server boots in development mode"
4
+ task :automatic_annotate => :environment do
5
+ unless File.exists?(File.join RAILS_INITIALIZERS_PATH, "automatic_annotation.rb")
6
+ f = File.open(File.join(RAILS_INITIALIZERS_PATH, "automatic_annotation.rb"), "w")
7
+ f.write <<-CODE
8
+ if RAILS_ENV == "development"
9
+ require 'annotate'
10
+ if Annotate.load_tasks
11
+ Rake::Task[:annotate_models].invoke
12
+ end
13
+ end
14
+ CODE
15
+ end
16
+ end
17
+
18
+ desc "Remove automatic annotation"
19
+ task :remove_automatic_annotation => :environment do
20
+ if File.exists?(f = File.join(RAILS_INITIALIZERS_PATH, "automatic_annotation.rb"))
21
+ File.delete(f)
22
+ end
23
+ end
@@ -0,0 +1,83 @@
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
+ 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,8 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Annotate do
4
+
5
+ it "should have more tests..heh" do
6
+ end
7
+
8
+ 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'
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: selleo-annotate
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.3.2
5
+ platform: ruby
6
+ authors:
7
+ - Cuong Tran
8
+ - Marcos Piccinini
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-10-23 00:00:00 +02:00
14
+ default_executable: annotate
15
+ dependencies: []
16
+
17
+ description:
18
+ email: x@selleo.com
19
+ executables:
20
+ - annotate
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README.rdoc
25
+ files:
26
+ - .gitignore
27
+ - History.txt
28
+ - README.rdoc
29
+ - Rakefile
30
+ - VERSION
31
+ - bin/annotate
32
+ - lib/annotate.rb
33
+ - lib/annotate/annotate_models.rb
34
+ - lib/annotate/annotate_routes.rb
35
+ - lib/tasks/annotate_models.rake
36
+ - lib/tasks/annotate_routes.rake
37
+ - lib/tasks/automatic_annotation.rake
38
+ - spec/annotate/annotate_models_spec.rb
39
+ - spec/annotate/annotate_routes_spec.rb
40
+ - spec/annotate_spec.rb
41
+ - spec/spec.opts
42
+ - spec/spec_helper.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/selleo/annotate
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Annotates Rails Models, routes, automatic annotation and others
71
+ test_files:
72
+ - spec/annotate_spec.rb
73
+ - spec/annotate/annotate_routes_spec.rb
74
+ - spec/annotate/annotate_models_spec.rb
75
+ - spec/spec_helper.rb