nofxx-annotate 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,27 @@
1
+ == 1.0.2 2008-03-22
2
+
3
+ * Add contributions from Michael Bumann (http://github.com/bumi)
4
+ * added an option "position" to choose to put the annotation,
5
+ * spec/fixtures now also get annotated
6
+ * added a task to remove the annotations
7
+ * these options can be specified from command line as -d and -p [before|after]
8
+
9
+ == 1.0.3 2008-05-02
10
+
11
+ * Add misc changes from Dustin Sallings and Henrik N
12
+ * Remove trailing whitespace
13
+ * More intuitive info messages
14
+ * Update README file with update-to-date example
15
+
16
+ == 2.0.0 2008-12-25
17
+
18
+ * Add annotate_models plugin fork additions
19
+ * Annotates Rspec and Test Unit models
20
+ * Annotates Object Daddy exemplars
21
+ * Annotates geometrical columns
22
+ * Add AnnotateRoutes rake task
23
+ * Up gem structure to newgem defaults
24
+
25
+
26
+
27
+
data/License.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2008 Dave Thomas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,66 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ annotate.gemspec
7
+ bin/annotate
8
+ config/hoe.rb
9
+ config/requirements.rb
10
+ lib/annotate.rb
11
+ lib/annotate_models/annotate_models.rb
12
+ lib/annotate_routes/annotate_routes.rb
13
+ lib/tasks/annotate_models.rake
14
+ lib/tasks/annotate_routes.rake
15
+ script/console
16
+ script/destroy
17
+ script/generate
18
+ setup.rb
19
+ spec/annotate_spec.rb
20
+ spec/spec.opts
21
+ spec/spec_helper.rb
22
+ tasks/rspec.rake
23
+ History.txt
24
+ License.txt
25
+ Manifest.txt
26
+ README.rdoc
27
+ Rakefile
28
+ annotate.gemspec
29
+ bin/annotate
30
+ config/hoe.rb
31
+ config/requirements.rb
32
+ lib/annotate.rb
33
+ lib/annotate_models/annotate_models.rb
34
+ lib/annotate_routes/annotate_routes.rb
35
+ lib/tasks/annotate_models.rake
36
+ lib/tasks/annotate_routes.rake
37
+ script/console
38
+ script/destroy
39
+ script/generate
40
+ setup.rb
41
+ spec/annotate_spec.rb
42
+ spec/spec.opts
43
+ spec/spec_helper.rb
44
+ tasks/rspec.rake
45
+ History.txt
46
+ License.txt
47
+ Manifest.txt
48
+ README.rdoc
49
+ Rakefile
50
+ annotate.gemspec
51
+ bin/annotate
52
+ config/hoe.rb
53
+ config/requirements.rb
54
+ lib/annotate.rb
55
+ lib/annotate_models/annotate_models.rb
56
+ lib/annotate_routes/annotate_routes.rb
57
+ lib/tasks/annotate_models.rake
58
+ lib/tasks/annotate_routes.rake
59
+ script/console
60
+ script/destroy
61
+ script/generate
62
+ setup.rb
63
+ spec/annotate_spec.rb
64
+ spec/spec.opts
65
+ spec/spec_helper.rb
66
+ tasks/rspec.rake
data/README.rdoc ADDED
@@ -0,0 +1,125 @@
1
+ _
2
+ /_| _/__/_
3
+ ( |/)/)()/(//(-
4
+ ________________
5
+
6
+
7
+ Add a comment summarizing the current schema to the bottom of each
8
+ ActiveRecord model, test file and fixture.
9
+ If you are using Object Daddy, it`ll annotate your example files too.
10
+
11
+ # == Schema Info
12
+ # Schema version: 20081001061831
13
+ #
14
+ # Table name: line_item
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
+ # Schema version: 20081213204851
31
+ #
32
+ # Table name: trips
33
+ #
34
+ # local :geometry point, 4326
35
+ # path :geometry line_string, 4326
36
+
37
+
38
+ == INSTALL
39
+
40
+ sudo gem install nofxx-annotate
41
+
42
+
43
+ == HOW TO USE:
44
+
45
+ To annotate all your models:
46
+
47
+ cd /path/to/app
48
+ annotate
49
+
50
+ To annotate routes.rb:
51
+
52
+ annotate -r
53
+
54
+
55
+ More:
56
+
57
+ annotate -h
58
+
59
+
60
+ To migrate & annotate (TODO):
61
+
62
+
63
+ Options:
64
+
65
+ Annotate on the head of the file:
66
+
67
+ annotate -p [before|after]
68
+
69
+
70
+ == WARNING
71
+
72
+ Note that this code will blow away the initial/final comment
73
+ block in your models if it looks like it was previously added
74
+ by annotate models, so you don't want to add additional text
75
+ to an automatically created comment block.
76
+
77
+ * * Back up your model files before using... * *
78
+
79
+ == LINKS
80
+
81
+ * Factory Girl => http://github.com/thoughtbot/factory_girl (NOT IMPLEMENTED)
82
+ * Object Daddy => http://github.com/flogic/object_daddy
83
+
84
+ * SpatialAdapter => http://github.com/pdeffendol/spatial_adapter
85
+ * PostgisAdapter => http://github.com/nofxx/postgis_adapter
86
+
87
+
88
+ == TODO
89
+
90
+ * Spec
91
+
92
+
93
+ == LICENSE:
94
+
95
+ Original code by:
96
+
97
+ Dave Thomas -- Pragmatic Programmers, LLC
98
+
99
+ Refactored, improved and maintained by:
100
+
101
+ Marcos Piccinini ( http://github.com/nofxx/annotate )
102
+
103
+ AnnotateModels mods by:
104
+
105
+ Alexander Semyonov ( http://github.com/rotuka/annotate_models )
106
+
107
+ AnnotateRoutes originally by:
108
+
109
+ Gavin Montague ( http://github.com/govan/annotate-routes )
110
+
111
+
112
+ == Forked from:
113
+
114
+ http://github.com/ctran/annotate_models
115
+
116
+
117
+ == Modifications
118
+ - alex@pivotallabs.com
119
+ - Cuong Tran - http://github.com/ctran
120
+ - Jack Danger - http://github.com/JackDanger
121
+ - Michael Bumann - http://github.com/bumi
122
+ - Henrik Nyh - http://github.com/henrik
123
+
124
+
125
+ Released under the same license as Ruby. No Support. No Warranty.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/annotate'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('annotate', Annotate::VERSION) do |p|
7
+ p.developer('Marcos Piccinini', 'x@nofxx.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.rubyforge_name = p.name
10
+ p.url = "http://github.com/nofxx/annotate"
11
+ p.summary = "Annotates Rails Models and Routes"
12
+ p.description = "Annotates Rails Models and Routes"
13
+
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
data/annotate.gemspec ADDED
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{annotate}
5
+ s.version = "2.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Marcos Piccinini"]
9
+ s.date = %q{2008-12-25}
10
+ s.default_executable = %q{annotate}
11
+ s.description = %q{Annotates Rails Models and Routes}
12
+ s.email = ["x@nofxx.com"]
13
+ s.executables = ["annotate"]
14
+ s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "README.rdoc"]
15
+ s.files = ["History.txt", "License.txt", "Manifest.txt", "README.rdoc", "Rakefile", "annotate.gemspec", "bin/annotate", "config/hoe.rb", "config/requirements.rb", "lib/annotate.rb", "lib/annotate_models/annotate_models.rb", "lib/annotate_routes/annotate_routes.rb", "lib/tasks/annotate_models.rake", "lib/tasks/annotate_routes.rake", "script/console", "script/destroy", "script/generate", "setup.rb", "spec/annotate_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/rspec.rake"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://github.com/nofxx/annotate}
18
+ s.rdoc_options = ["--main", "README.rdoc"]
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{annotate}
21
+ s.rubygems_version = %q{1.3.1}
22
+ s.summary = %q{Annotates Rails Models and Routes}
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_development_dependency(%q<newgem>, [">= 1.2.1"])
30
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
31
+ else
32
+ s.add_dependency(%q<newgem>, [">= 1.2.1"])
33
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<newgem>, [">= 1.2.1"])
37
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
38
+ end
39
+ end
data/bin/annotate ADDED
@@ -0,0 +1,16 @@
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') { task = :remove_annotation }
11
+ opts.on('-p', '--position [before|after]', ['before', 'after']) { |p| ENV['position'] = p }
12
+ opts.on('-r', '--routes') { task = :annotate_routes }
13
+ opts.on('-v', '--version') { puts "Annotate v#{Annotate::VERSION}"; exit }
14
+ end.parse!
15
+
16
+ Rake::Task[task].invoke
data/config/hoe.rb ADDED
@@ -0,0 +1,69 @@
1
+ require 'annotate_models/version'
2
+
3
+ AUTHOR = 'Dave Thomas' # can also be an array of Authors
4
+ EMAIL = "ctran@pragmaquest.com"
5
+ DESCRIPTION = "Add a comment summarizing the current schema to the top of each ActiveRecord model source file"
6
+ GEM_NAME = 'annotate-models' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'annotate-models' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = AnnotateModels::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'annotate_models documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.developer(AUTHOR, EMAIL)
52
+ p.description = DESCRIPTION
53
+ p.summary = DESCRIPTION
54
+ p.url = HOMEPATH
55
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
56
+ p.test_globs = ["test/**/test_*.rb"]
57
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
58
+
59
+ # == Optional
60
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
61
+ p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
62
+ p.spec_extras = {} # A hash of extra values to set in the gemspec.
63
+
64
+ end
65
+
66
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
67
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
68
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
69
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'annotate_models'
data/lib/annotate.rb ADDED
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module Annotate
5
+ VERSION = '2.1.1'
6
+ end
7
+
8
+
9
+ load 'Rakefile'
10
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |rake| load rake }
11
+
@@ -0,0 +1,221 @@
1
+ module AnnotateModels
2
+ class << self
3
+ MODEL_DIR = "app/models"
4
+ FIXTURE_DIRS = ["test/fixtures","spec/fixtures"]
5
+ UNIT_TEST_DIR = File.join(RAILS_ROOT, "test/unit" )
6
+ SPEC_MODEL_DIR = File.join(RAILS_ROOT, "spec/models")
7
+ # Object Daddy http://github.com/flogic/object_daddy/tree/master
8
+ EXEMPLARS_DIR = File.join(RAILS_ROOT, "spec/exemplars")
9
+ PREFIX = "== Schema Information"
10
+ # Annotate Models as plugin use this header
11
+ COMPAT_PREFIX = "== Schema Info"
12
+
13
+ # Simple quoting for the default column value
14
+ def quote(value)
15
+ case value
16
+ when NilClass then "NULL"
17
+ when TrueClass then "TRUE"
18
+ when FalseClass then "FALSE"
19
+ when Float, Fixnum, Bignum then value.to_s
20
+ # BigDecimals need to be output in a non-normalized form and quoted.
21
+ when BigDecimal then value.to_s('F')
22
+ else
23
+ value.inspect
24
+ end
25
+ end
26
+
27
+ # Use the column information in an ActiveRecord class
28
+ # to create a comment block containing a line for
29
+ # each column. The line contains the column name,
30
+ # the type (and length), and any optional attributes
31
+ def get_schema_info(klass, header)
32
+ info = "# #{header}\n#\n"
33
+ info << "# Table name: #{klass.table_name}\n#\n"
34
+
35
+ max_size = klass.column_names.collect{|name| name.size}.max + 1
36
+ klass.columns.each do |col|
37
+ attrs = []
38
+ attrs << "default(#{quote(col.default)})" if col.default
39
+ attrs << "not null" unless col.null
40
+ attrs << "primary key" if col.name == klass.primary_key
41
+
42
+ col_type = col.type.to_s
43
+ if col_type == "decimal"
44
+ col_type << "(#{col.precision}, #{col.scale})"
45
+ else
46
+ col_type << "(#{col.limit})" if col.limit
47
+ end
48
+
49
+ # Check out if we got a geometric column
50
+ # and print the type and SRID
51
+ if col.respond_to?(:geometry_type)
52
+ attrs << "#{col.geometry_type}, #{col.srid}"
53
+ end
54
+
55
+ info << sprintf("# %-#{max_size}.#{max_size}s:%-15.15s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n"
56
+ end
57
+
58
+ info << "#\n\n"
59
+ end
60
+
61
+ # Add a schema block to a file. If the file already contains
62
+ # a schema info block (a comment starting with "== Schema Information"), check if it
63
+ # matches the block that is already there. If so, leave it be. If not, remove the old
64
+ # info block and write a new one.
65
+ # Returns true or false depending on whether the file was modified.
66
+ #
67
+ # === Options (opts)
68
+ # :position<Symbol>:: where to place the annotated section in fixture or model file,
69
+ # "before" or "after". Default is "before".
70
+ # :position_in_class<Symbol>:: where to place the annotated section in model file
71
+ # :position_in_fixture<Symbol>:: where to place the annotated section in fixture file
72
+ #
73
+ def annotate_one_file(file_name, info_block, options={})
74
+ if File.exist?(file_name)
75
+ old_content = File.read(file_name)
76
+
77
+ # Ignore the Schema version line because it changes with each migration
78
+ header = Regexp.new(/(^# Table name:.*?\n(#.*\n)*\n)/)
79
+ old_header = old_content.match(header).to_s
80
+ new_header = info_block.match(header).to_s
81
+
82
+ if old_header == new_header
83
+ false
84
+ else
85
+ # Remove old schema info
86
+ old_content.sub!(/^# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n/, '')
87
+
88
+ # Write it back
89
+ new_content = options[:position] == "before" ? (info_block + old_content) : (old_content + "\n" + info_block)
90
+
91
+ File.open(file_name, "wb") { |f| f.puts new_content }
92
+ true
93
+ end
94
+ end
95
+ end
96
+
97
+ def remove_annotation_of_file(file_name)
98
+ if File.exist?(file_name)
99
+ content = File.read(file_name)
100
+
101
+ content.sub!(/^# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n/, '')
102
+
103
+ File.open(file_name, "wb") { |f| f.puts content }
104
+ end
105
+ end
106
+
107
+ # Given the name of an ActiveRecord class, create a schema
108
+ # info block (basically a comment containing information
109
+ # on the columns and their types) and put it at the front
110
+ # of the model and fixture source files.
111
+ # Returns true or false depending on whether the source
112
+ # files were modified.
113
+
114
+ def annotate(klass, file, header,options={})
115
+ info = get_schema_info(klass, header)
116
+ annotated = false
117
+ model_name = klass.name.underscore
118
+ model_file_name = File.join(MODEL_DIR, file)
119
+ if annotate_one_file(model_file_name, info, options.merge(
120
+ :position=>(options[:position_in_class] || options[:position])))
121
+ annotated = true
122
+ end
123
+
124
+ [
125
+ File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"), # test
126
+ File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"), # spec
127
+ File.join(EXEMPLARS_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
128
+ ].each { |file| annotate_one_file(file, info) }
129
+
130
+ FIXTURE_DIRS.each do |dir|
131
+ fixture_file_name = File.join(dir,klass.table_name + ".yml")
132
+ annotate_one_file(fixture_file_name, info, options.merge(:position=>(options[:position_in_fixture] || options[:position]))) if File.exist?(fixture_file_name)
133
+ end
134
+ annotated
135
+ end
136
+
137
+ # Return a list of the model files to annotate. If we have
138
+ # command line arguments, they're assumed to be either
139
+ # the underscore or CamelCase versions of model names.
140
+ # Otherwise we take all the model files in the
141
+ # app/models directory.
142
+ def get_model_files
143
+ models = ARGV.dup
144
+ models.shift
145
+ models.reject!{|m| m.starts_with?("position=")}
146
+ if models.empty?
147
+ Dir.chdir(MODEL_DIR) do
148
+ models = Dir["**/*.rb"]
149
+ end
150
+ end
151
+ models
152
+ end
153
+
154
+ # Retrieve the classes belonging to the model names we're asked to process
155
+ # Check for namespaced models in subdirectories as well as models
156
+ # in subdirectories without namespacing.
157
+ def get_model_class(file)
158
+ model = file.gsub(/\.rb$/, '').camelize
159
+ parts = model.split('::')
160
+ begin
161
+ parts.inject(Object) {|klass, part| klass.const_get(part) }
162
+ rescue LoadError
163
+ Object.const_get(parts.last)
164
+ end
165
+ end
166
+
167
+ # We're passed a name of things that might be
168
+ # ActiveRecord models. If we can find the class, and
169
+ # if its a subclass of ActiveRecord::Base,
170
+ # then pas it to the associated block
171
+ def do_annotations(options={})
172
+ header = PREFIX.dup
173
+ version = ActiveRecord::Migrator.current_version rescue 0
174
+ if version > 0
175
+ header << "\n# Schema version: #{version}"
176
+ end
177
+
178
+ annotated = []
179
+ get_model_files.each do |file|
180
+ begin
181
+ klass = get_model_class(file)
182
+ if klass < ActiveRecord::Base && !klass.abstract_class?
183
+ if annotate(klass, file, header,options)
184
+ annotated << klass
185
+ end
186
+ end
187
+ rescue Exception => e
188
+ puts "Unable to annotate #{file}: #{e.message}"
189
+ end
190
+ end
191
+ if annotated.empty?
192
+ puts "Nothing annotated!"
193
+ else
194
+ puts "Annotated (#{annotated.length}): #{annotated.join(', ')}"
195
+ end
196
+ end
197
+
198
+ def remove_annotations
199
+ deannotated = []
200
+ get_model_files.each do |file|
201
+ begin
202
+ klass = get_model_class(file)
203
+ if klass < ActiveRecord::Base && !klass.abstract_class?
204
+ deannotated << klass
205
+
206
+ model_file_name = File.join(MODEL_DIR, file)
207
+ remove_annotation_of_file(model_file_name)
208
+
209
+ FIXTURE_DIRS.each do |dir|
210
+ fixture_file_name = File.join(dir,klass.table_name + ".yml")
211
+ remove_annotation_of_file(fixture_file_name) if File.exist?(fixture_file_name)
212
+ end
213
+ end
214
+ rescue Exception => e
215
+ puts "Unable to annotate #{file}: #{e.message}"
216
+ end
217
+ end
218
+ puts "Removed annotation from: #{deannotated.join(', ')}"
219
+ end
220
+ end
221
+ end