annotate 2.5.0 → 2.6.0.beta2

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.
@@ -1,17 +1,150 @@
1
- here = File.dirname __FILE__
2
- require "#{here}/annotate/version"
1
+ $:.unshift(File.dirname(__FILE__))
2
+ require 'annotate/version'
3
+ require 'annotate/annotate_models'
4
+ require 'annotate/annotate_routes'
5
+
6
+ begin
7
+ # ActiveSupport 3.x...
8
+ require 'active_support/hash_with_indifferent_access'
9
+ rescue Exception => e
10
+ # ActiveSupport 2.x...
11
+ require 'active_support/core_ext/hash/indifferent_access'
12
+ end
3
13
 
4
14
  module Annotate
15
+ ##
16
+ # The set of available options to customize the behavior of Annotate.
17
+ #
18
+ POSITION_OPTIONS=[
19
+ :position_in_routes, :position_in_class, :position_in_test,
20
+ :position_in_fixture, :position_in_factory, :position,
21
+ ]
22
+ FLAG_OPTIONS=[
23
+ :show_indexes, :simple_indexes, :include_version, :exclude_tests,
24
+ :exclude_fixtures, :exclude_factories, :ignore_model_sub_dir,
25
+ :format_bare, :format_rdoc, :format_markdown, :sort, :force, :trace,
26
+ ]
27
+ OTHER_OPTIONS=[
28
+ :model_dir,
29
+ ]
30
+ PATH_OPTIONS=[
31
+ :require,
32
+ ]
33
+
34
+
35
+ ##
36
+ # Set default values that can be overridden via environment variables.
37
+ #
38
+ def self.set_defaults(options = {})
39
+ return if(@has_set_defaults)
40
+ @has_set_defaults = true
41
+ options = HashWithIndifferentAccess.new(options)
42
+ [POSITION_OPTIONS, FLAG_OPTIONS, PATH_OPTIONS].flatten.each do |key|
43
+ if(options.has_key?(key))
44
+ default_value = if(options[key].is_a?(Array))
45
+ options[key].join(",")
46
+ else
47
+ options[key]
48
+ end
49
+ end
50
+ default_value = ENV[key.to_s] if(!ENV[key.to_s].blank?)
51
+ ENV[key.to_s] = default_value.to_s
52
+ end
53
+ end
54
+
55
+ TRUE_RE = /^(true|t|yes|y|1)$/i
56
+ def self.setup_options(options = {})
57
+ POSITION_OPTIONS.each do |key|
58
+ options[key] = fallback(ENV[key.to_s], ENV['position'], 'before')
59
+ end
60
+ FLAG_OPTIONS.each do |key|
61
+ options[key] = true?(ENV[key.to_s])
62
+ end
63
+ OTHER_OPTIONS.each do |key|
64
+ options[key] = (!ENV[key.to_s].blank?) ? ENV[key.to_s] : nil
65
+ end
66
+ PATH_OPTIONS.each do |key|
67
+ options[key] = (!ENV[key.to_s].blank?) ? ENV[key.to_s].split(',') : []
68
+ end
69
+
70
+ if(!options[:model_dir])
71
+ options[:model_dir] = 'app/models'
72
+ end
73
+
74
+ return options
75
+ end
76
+
77
+ def self.skip_on_migration?
78
+ ENV['skip_on_db_migrate'] =~ TRUE_RE
79
+ end
80
+
81
+ def self.loaded_tasks=(val); @loaded_tasks = val; end
82
+ def self.loaded_tasks; return @loaded_tasks; end
83
+
5
84
  def self.load_tasks
6
- if File.exists?('Rakefile')
7
- require 'rake'
8
- load 'Rakefile'
9
- # Rails 3 wants to load our .rake files for us.
10
- # TODO: selectively do this require on Rails 2.x?
11
- Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |rake| load rake }
12
- return true
85
+ return if(self.loaded_tasks)
86
+ self.loaded_tasks = true
87
+
88
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |rake| load rake }
89
+ end
90
+
91
+ def self.load_requires(options)
92
+ options[:require].each { |path| require path } if options[:require].count > 0
93
+ end
94
+
95
+ def self.eager_load(options)
96
+ self.load_requires(options)
97
+ require "annotate/active_record_patch"
98
+
99
+ if(defined?(Rails))
100
+ if(Rails.version.split('.').first.to_i < 3)
101
+ Rails.configuration.eager_load_paths.each do |load_path|
102
+ matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
103
+ Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
104
+ require_dependency file.sub(matcher, '\1')
105
+ end
106
+ end
107
+ else
108
+ klass = Rails::Application.send(:subclasses).first
109
+ klass.eager_load!
110
+ end
13
111
  else
14
- return false
112
+ FileList["#{options[:model_dir]}/**/*.rb"].each do |fname|
113
+ require File.expand_path(fname)
114
+ end
15
115
  end
16
116
  end
117
+
118
+ def self.bootstrap_rake
119
+ begin
120
+ require 'rake/dsl_definition'
121
+ rescue Exception => e
122
+ # We might just be on an old version of Rake...
123
+ end
124
+ require 'rake'
125
+
126
+ if File.exists?('./Rakefile')
127
+ load './Rakefile'
128
+ end
129
+ Rake::Task[:environment].invoke rescue nil
130
+ if(!defined?(Rails))
131
+ # Not in a Rails project, so time to load up the parts of
132
+ # ActiveSupport we need.
133
+ require 'active_support'
134
+ require 'active_support/core_ext/class/subclasses'
135
+ require 'active_support/core_ext/string/inflections'
136
+ end
137
+ self.load_tasks
138
+ Rake::Task[:set_annotation_options].invoke
139
+ end
140
+
141
+ def self.fallback(*args)
142
+ return args.detect { |arg| !arg.blank? }
143
+ end
144
+
145
+ def self.true?(val)
146
+ return false if(val.blank?)
147
+ return false unless(val =~ TRUE_RE)
148
+ return true
149
+ end
17
150
  end
@@ -6,4 +6,4 @@ module ::ActiveRecord
6
6
  # ignore this, so unknown/unloaded macros won't cause parsing to fail
7
7
  end
8
8
  end
9
- end
9
+ end
@@ -9,11 +9,10 @@ module AnnotateModels
9
9
 
10
10
  # File.join for windows reverse bar compat?
11
11
  # I dont use windows, can`t test
12
- UNIT_TEST_DIR = File.join("test", "unit" )
12
+ UNIT_TEST_DIR = File.join("test", "unit")
13
13
  SPEC_MODEL_DIR = File.join("spec", "models")
14
14
  FIXTURE_TEST_DIR = File.join("test", "fixtures")
15
15
  FIXTURE_SPEC_DIR = File.join("spec", "fixtures")
16
- FIXTURE_DIRS = ["test/fixtures","spec/fixtures"]
17
16
 
18
17
  # Object Daddy http://github.com/flogic/object_daddy/tree/master
19
18
  EXEMPLARS_TEST_DIR = File.join("test", "exemplars")
@@ -31,6 +30,29 @@ module AnnotateModels
31
30
  FABRICATORS_TEST_DIR = File.join("test", "fabricators")
32
31
  FABRICATORS_SPEC_DIR = File.join("spec", "fabricators")
33
32
 
33
+ TEST_PATTERNS = [
34
+ [UNIT_TEST_DIR, "%MODEL_NAME%_test.rb"],
35
+ [SPEC_MODEL_DIR, "%MODEL_NAME%_spec.rb"],
36
+ ]
37
+
38
+ FIXTURE_PATTERNS = [
39
+ File.join(FIXTURE_TEST_DIR, "%TABLE_NAME%.yml"),
40
+ File.join(FIXTURE_SPEC_DIR, "%TABLE_NAME%.yml"),
41
+ ]
42
+
43
+ FACTORY_PATTERNS = [
44
+ File.join(EXEMPLARS_TEST_DIR, "%MODEL_NAME%_exemplar.rb"),
45
+ File.join(EXEMPLARS_SPEC_DIR, "%MODEL_NAME%_exemplar.rb"),
46
+ File.join(BLUEPRINTS_TEST_DIR, "%MODEL_NAME%_blueprint.rb"),
47
+ File.join(BLUEPRINTS_SPEC_DIR, "%MODEL_NAME%_blueprint.rb"),
48
+ File.join(FACTORY_GIRL_TEST_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
49
+ File.join(FACTORY_GIRL_SPEC_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
50
+ File.join(FACTORY_GIRL_TEST_DIR, "%TABLE_NAME%.rb"), # (new style)
51
+ File.join(FACTORY_GIRL_SPEC_DIR, "%TABLE_NAME%.rb"), # (new style)
52
+ File.join(FABRICATORS_TEST_DIR, "%MODEL_NAME%_fabricator.rb"),
53
+ File.join(FABRICATORS_SPEC_DIR, "%MODEL_NAME%_fabricator.rb"),
54
+ ]
55
+
34
56
  # Don't show limit (#) on these column types
35
57
  # Example: show "integer" instead of "integer(4)"
36
58
  NO_LIMIT_COL_TYPES = ["integer", "boolean"]
@@ -39,7 +61,7 @@ module AnnotateModels
39
61
  def model_dir
40
62
  @model_dir || "app/models"
41
63
  end
42
-
64
+
43
65
  def model_dir=(dir)
44
66
  @model_dir = dir
45
67
  end
@@ -65,15 +87,24 @@ module AnnotateModels
65
87
  def get_schema_info(klass, header, options = {})
66
88
  info = "# #{header}\n"
67
89
  info<< "#\n"
68
- info<< "# Table name: #{klass.table_name}\n"
90
+ if(options[:format_markdown])
91
+ info<< "# Table name: `#{klass.table_name}`\n"
92
+ info<< "#\n"
93
+ info<< "# ### Columns\n"
94
+ else
95
+ info<< "# Table name: #{klass.table_name}\n"
96
+ end
69
97
  info<< "#\n"
70
98
 
71
99
  max_size = klass.column_names.map{|name| name.size}.max || 0
72
100
  max_size += options[:format_rdoc] ? 5 : 1
101
+ md_names_overhead = 6
102
+ md_type_allowance = 18
103
+ bare_type_allowance = 16
73
104
 
74
105
  if(options[:format_markdown])
75
- info<< sprintf( "# %-#{max_size + 4}.#{max_size + 4}s | %-18.18s | %s\n", 'Field', 'Type', 'Attributes' )
76
- info<< "# #{ '-' * ( max_size + 4 ) } | #{'-' * 18} | #{ '-' * 25 }\n"
106
+ info<< sprintf( "# %-#{max_size + md_names_overhead}.#{max_size + md_names_overhead}s | %-#{md_type_allowance}.#{md_type_allowance}s | %s\n", 'Name', 'Type', 'Attributes' )
107
+ info<< "# #{ '-' * ( max_size + md_names_overhead ) } | #{'-' * md_type_allowance} | #{ '-' * 27 }\n"
77
108
  end
78
109
 
79
110
  cols = klass.columns
@@ -82,7 +113,7 @@ module AnnotateModels
82
113
  attrs = []
83
114
  attrs << "default(#{quote(col.default)})" unless col.default.nil?
84
115
  attrs << "not null" unless col.null
85
- attrs << "primary key" if klass.primary_key && col.name.to_sym == klass.primary_key.to_sym
116
+ attrs << "primary key" if klass.primary_key && (klass.primary_key.is_a?(Array) ? klass.primary_key.collect{|c|c.to_sym}.include?(col.name.to_sym) : col.name.to_sym == klass.primary_key.to_sym)
86
117
 
87
118
  col_type = (col.type || col.sql_type).to_s
88
119
  if col_type == "decimal"
@@ -92,7 +123,7 @@ module AnnotateModels
92
123
  col_type << "(#{col.limit})" unless NO_LIMIT_COL_TYPES.include?(col_type)
93
124
  end
94
125
  end
95
-
126
+
96
127
  # Check out if we got a geometric column
97
128
  # and print the type and SRID
98
129
  if col.respond_to?(:geometry_type)
@@ -114,14 +145,16 @@ module AnnotateModels
114
145
  if options[:format_rdoc]
115
146
  info << sprintf("# %-#{max_size}.#{max_size}s<tt>%s</tt>", "*#{col.name}*::", attrs.unshift(col_type).join(", ")).rstrip + "\n"
116
147
  elsif options[:format_markdown]
117
- info << sprintf("# **%-#{max_size}.#{max_size}s** | `%-16.16s` | `%s`", col.name, col_type, attrs.join(", ").rstrip) + "\n"
148
+ name_remainder = max_size - col.name.length
149
+ type_remainder = (md_type_allowance - 2) - col_type.length
150
+ info << (sprintf("# **`%s`**%#{name_remainder}s | `%s`%#{type_remainder}s | `%s`", col.name, " ", col_type, " ", attrs.join(", ").rstrip)).gsub('``', ' ').rstrip + "\n"
118
151
  else
119
- info << sprintf("# %-#{max_size}.#{max_size}s:%-16.16s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n"
152
+ info << sprintf("# %-#{max_size}.#{max_size}s:%-#{bare_type_allowance}.#{bare_type_allowance}s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n"
120
153
  end
121
154
  end
122
155
 
123
156
  if options[:show_indexes] && klass.table_exists?
124
- info << get_index_info(klass)
157
+ info << get_index_info(klass, options)
125
158
  end
126
159
 
127
160
  if options[:format_rdoc]
@@ -133,15 +166,23 @@ module AnnotateModels
133
166
  end
134
167
  end
135
168
 
136
- def get_index_info(klass)
137
- index_info = "#\n# Indexes\n#\n"
169
+ def get_index_info(klass, options={})
170
+ if(options[:format_markdown])
171
+ index_info = "#\n# ### Indexes\n#\n"
172
+ else
173
+ index_info = "#\n# Indexes\n#\n"
174
+ end
138
175
 
139
176
  indexes = klass.connection.indexes(klass.table_name)
140
177
  return "" if indexes.empty?
141
178
 
142
179
  max_size = indexes.collect{|index| index.name.size}.max + 1
143
180
  indexes.sort_by{|index| index.name}.each do |index|
144
- index_info << sprintf("# %-#{max_size}.#{max_size}s %s %s", index.name, "(#{index.columns.join(",")})", index.unique ? "UNIQUE" : "").rstrip + "\n"
181
+ if(options[:format_markdown])
182
+ index_info << sprintf("# * `%s`%s:\n# * **`%s`**\n", index.name, index.unique ? " (_unique_)" : "", index.columns.join("`**\n# * **`"))
183
+ else
184
+ index_info << sprintf("# %-#{max_size}.#{max_size}s %s %s", index.name, "(#{index.columns.join(",")})", index.unique ? "UNIQUE" : "").rstrip + "\n"
185
+ end
145
186
  end
146
187
  return index_info
147
188
  end
@@ -153,14 +194,11 @@ module AnnotateModels
153
194
  # Returns true or false depending on whether the file was modified.
154
195
  #
155
196
  # === Options (opts)
156
- # :position<Symbol>:: where to place the annotated section in fixture or model file,
157
- # :before or :after. Default is :before.
158
- # :position_in_class<Symbol>:: where to place the annotated section in model file
159
- # :position_in_fixture<Symbol>:: where to place the annotated section in fixture file
160
- # :position_in_others<Symbol>:: where to place the annotated section in the rest of
161
- # supported files
197
+ # :force<Symbol>:: whether to update the file even if it doesn't seem to need it.
198
+ # :position_in_*<Symbol>:: where to place the annotated section in fixture or model file,
199
+ # :before or :after. Default is :before.
162
200
  #
163
- def annotate_one_file(file_name, info_block, options={})
201
+ def annotate_one_file(file_name, info_block, position, options={})
164
202
  if File.exist?(file_name)
165
203
  old_content = File.read(file_name)
166
204
  return false if(old_content =~ /# -\*- SkipSchemaAnnotations.*\n/)
@@ -178,9 +216,9 @@ module AnnotateModels
178
216
  encoding_header = old_content.match(encoding).to_s
179
217
 
180
218
  if old_columns == new_columns && !options[:force]
181
- false
219
+ return false
182
220
  else
183
-
221
+
184
222
  # todo: figure out if we need to extract any logic from this merge chunk
185
223
  # <<<<<<< HEAD
186
224
  # # Replace the old schema info with the new schema info
@@ -197,22 +235,30 @@ module AnnotateModels
197
235
  # Strip the old schema info, and insert new schema info.
198
236
  old_content.sub!(encoding, '')
199
237
  old_content.sub!(PATTERN, '')
200
-
201
- new_content = (options[:position] || 'before').to_s == 'after' ?
238
+
239
+ new_content = options[position].to_s == 'after' ?
202
240
  (encoding_header + (old_content.rstrip + "\n\n" + info_block)) :
203
241
  (encoding_header + info_block + old_content)
204
242
 
205
243
  File.open(file_name, "wb") { |f| f.puts new_content }
206
- true
244
+ return true
207
245
  end
246
+ else
247
+ return false
208
248
  end
209
249
  end
210
-
250
+
211
251
  def remove_annotation_of_file(file_name)
212
252
  if File.exist?(file_name)
213
253
  content = File.read(file_name)
254
+
214
255
  content.sub!(PATTERN, '')
256
+
215
257
  File.open(file_name, "wb") { |f| f.puts content }
258
+
259
+ return true
260
+ else
261
+ return false
216
262
  end
217
263
  end
218
264
 
@@ -222,48 +268,55 @@ module AnnotateModels
222
268
  # of the model and fixture source files.
223
269
  # Returns true or false depending on whether the source
224
270
  # files were modified.
271
+ #
272
+ # === Options (opts)
273
+ # :position_in_class<Symbol>:: where to place the annotated section in model file
274
+ # :position_in_test<Symbol>:: where to place the annotated section in test/spec file(s)
275
+ # :position_in_fixture<Symbol>:: where to place the annotated section in fixture file
276
+ # :position_in_factory<Symbol>:: where to place the annotated section in factory file
277
+ # :exclude_tests<Symbol>:: whether to skip modification of test/spec files
278
+ # :exclude_fixtures<Symbol>:: whether to skip modification of fixture files
279
+ # :exclude_factories<Symbol>:: whether to skip modification of factory files
280
+ #
225
281
  def annotate(klass, file, header, options={})
226
- info = get_schema_info(klass, header, options)
227
- annotated = false
228
- model_name = klass.name.underscore
229
- model_file_name = File.join(model_dir, file)
282
+ begin
283
+ info = get_schema_info(klass, header, options)
284
+ did_annotate = false
285
+ model_name = klass.name.underscore
286
+ table_name = klass.table_name
287
+ model_file_name = File.join(model_dir, file)
288
+
289
+ if annotate_one_file(model_file_name, info, :position_in_class, options_with_position(options, :position_in_class))
290
+ did_annotate = true
291
+ end
230
292
 
231
- if annotate_one_file(model_file_name, info, options_with_position(options, :position_in_class))
232
- annotated = true
233
- end
293
+ unless options[:exclude_tests]
294
+ did_annotate = TEST_PATTERNS.
295
+ map { |pat| [pat[0], resolve_filename(pat[1], model_name, table_name)] }.
296
+ map { |pat| find_test_file(*pat) }.
297
+ map { |file| annotate_one_file(file, info, :position_in_test, options_with_position(options, :position_in_test)) }.
298
+ detect { |result| result } || did_annotate
299
+ end
234
300
 
235
- unless options[:exclude_tests]
236
- [
237
- find_test_file(UNIT_TEST_DIR, "#{model_name}_test.rb"), # test
238
- find_test_file(SPEC_MODEL_DIR, "#{model_name}_spec.rb"), # spec
239
- ].each do |file|
240
- # todo: add an option "position_in_test" -- or maybe just ask if anyone ever wants different positions for model vs. test vs. fixture
241
- if annotate_one_file(file, info, options_with_position(options, :position_in_fixture))
242
- annotated = true
243
- end
301
+ unless options[:exclude_fixtures]
302
+ did_annotate = FIXTURE_PATTERNS.
303
+ map { |file| resolve_filename(file, model_name, table_name) }.
304
+ map { |file| annotate_one_file(file, info, :position_in_fixture, options_with_position(options, :position_in_fixture)) }.
305
+ detect { |result| result } || did_annotate
244
306
  end
245
- end
246
307
 
247
- unless options[:exclude_fixtures]
248
- [
249
- File.join(FIXTURE_TEST_DIR, "#{klass.table_name}.yml"), # fixture
250
- File.join(FIXTURE_SPEC_DIR, "#{klass.table_name}.yml"), # fixture
251
- File.join(EXEMPLARS_TEST_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
252
- File.join(EXEMPLARS_SPEC_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
253
- File.join(BLUEPRINTS_TEST_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
254
- File.join(BLUEPRINTS_SPEC_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
255
- File.join(FACTORY_GIRL_TEST_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
256
- File.join(FACTORY_GIRL_SPEC_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
257
- File.join(FABRICATORS_TEST_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
258
- File.join(FABRICATORS_SPEC_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
259
- ].each do |file|
260
- if annotate_one_file(file, info, options_with_position(options, :position_in_fixture))
261
- annotated = true
262
- end
308
+ unless options[:exclude_factories]
309
+ did_annotate = FACTORY_PATTERNS.
310
+ map { |file| resolve_filename(file, model_name, table_name) }.
311
+ map { |file| annotate_one_file(file, info, :position_in_factory, options_with_position(options, :position_in_factory)) }.
312
+ detect { |result| result } || did_annotate
263
313
  end
264
- end
265
314
 
266
- annotated
315
+ return did_annotate
316
+ rescue Exception => e
317
+ puts "Unable to annotate #{file}: #{e.message}"
318
+ puts "\t" + e.backtrace.join("\n\t") if options[:trace]
319
+ end
267
320
  end
268
321
 
269
322
  # position = :position_in_fixture or :position_in_class
@@ -297,19 +350,18 @@ module AnnotateModels
297
350
  puts "No models found in directory '#{model_dir}'."
298
351
  puts "Either specify models on the command line, or use the --model-dir option."
299
352
  puts "Call 'annotate --help' for more info."
300
- exit 1;
353
+ exit 1
301
354
  end
302
355
  end
303
356
  models
304
357
  end
305
-
358
+
306
359
  # Retrieve the classes belonging to the model names we're asked to process
307
360
  # Check for namespaced models in subdirectories as well as models
308
361
  # in subdirectories without namespacing.
309
362
  def get_model_class(file)
310
363
  # this is for non-rails projects, which don't get Rails auto-require magic
311
- require File.expand_path("#{model_dir}/#{file}")
312
-
364
+ require File.expand_path("#{model_dir}/#{file}") unless Module.const_defined?(:Rails)
313
365
  model_path = file.gsub(/\.rb$/, '')
314
366
  get_loaded_model(model_path) || get_loaded_model(model_path.split('/').last)
315
367
  end
@@ -320,7 +372,7 @@ module AnnotateModels
320
372
  select do |c|
321
373
  Class === c and # note: we use === to avoid a bug in activesupport 2.3.14 OptionMerger vs. is_a?
322
374
  c.ancestors.respond_to?(:include?) and # to fix FactoryGirl bug, see https://github.com/ctran/annotate_models/pull/82
323
- c.ancestors.include?(ActiveRecord::Base)
375
+ c.ancestors.include?(ActiveRecord::Base)
324
376
  end.
325
377
  detect { |c| ActiveSupport::Inflector.underscore(c) == model_path }
326
378
  end
@@ -330,21 +382,15 @@ module AnnotateModels
330
382
  # if its a subclass of ActiveRecord::Base,
331
383
  # then pass it to the associated block
332
384
  def do_annotations(options={})
333
- if options[:require]
334
- options[:require].each do |path|
335
- require path
336
- end
337
- end
338
-
339
385
  header = options[:format_markdown] ? PREFIX_MD.dup : PREFIX.dup
340
386
 
341
387
  if options[:include_version]
342
388
  version = ActiveRecord::Migrator.current_version rescue 0
343
389
  if version > 0
344
390
  header << "\n# Schema version: #{version}"
345
- end
391
+ end
346
392
  end
347
-
393
+
348
394
  self.model_dir = options[:model_dir] if options[:model_dir]
349
395
 
350
396
  annotated = []
@@ -373,46 +419,54 @@ module AnnotateModels
373
419
  end
374
420
 
375
421
  def remove_annotations(options={})
422
+
376
423
  self.model_dir = options[:model_dir] if options[:model_dir]
377
424
  deannotated = []
425
+ deannotated_klass = false
378
426
  get_model_files(options).each do |file|
379
427
  begin
380
428
  klass = get_model_class(file)
381
429
  if klass < ActiveRecord::Base && !klass.abstract_class?
382
- deannotated << klass
383
-
384
430
  model_name = klass.name.underscore
431
+ table_name = klass.table_name
385
432
  model_file_name = File.join(model_dir, file)
386
- remove_annotation_of_file(model_file_name)
387
-
388
- [
389
- File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"),
390
- File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"),
391
- File.join(FIXTURE_TEST_DIR, "#{klass.table_name}.yml"), # fixture
392
- File.join(FIXTURE_SPEC_DIR, "#{klass.table_name}.yml"), # fixture
393
- File.join(EXEMPLARS_TEST_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
394
- File.join(EXEMPLARS_SPEC_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
395
- File.join(BLUEPRINTS_TEST_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
396
- File.join(BLUEPRINTS_SPEC_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
397
- File.join(FACTORY_GIRL_TEST_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
398
- File.join(FACTORY_GIRL_SPEC_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
399
- File.join(FABRICATORS_TEST_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
400
- File.join(FABRICATORS_SPEC_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
401
- ].each do |file|
402
- remove_annotation_of_file(file) if File.exist?(file)
403
- end
404
-
433
+ deannotated_klass = true if(remove_annotation_of_file(model_file_name))
434
+
435
+ TEST_PATTERNS.
436
+ map { |pat| [pat[0], resolve_filename(pat[1], model_name, table_name)]}.
437
+ map { |pat| find_test_file(*pat) }.each do |file|
438
+ if(File.exist?(file))
439
+ remove_annotation_of_file(file)
440
+ deannotated_klass = true
441
+ end
442
+ end
443
+
444
+ (FIXTURE_PATTERNS + FACTORY_PATTERNS).
445
+ map { |file| resolve_filename(file, model_name, table_name) }.
446
+ each do |file|
447
+ if File.exist?(file)
448
+ remove_annotation_of_file(file)
449
+ deannotated_klass = true
450
+ end
451
+ end
405
452
  end
453
+ deannotated << klass if(deannotated_klass)
406
454
  rescue Exception => e
407
455
  puts "Unable to deannotate #{file}: #{e.message}"
408
- puts "\t" + e.backtrace.join("\n\t") if options[:trace]
456
+ puts "\t" + e.backtrace.join("\n\t") if options[:trace]
409
457
  end
410
458
  end
411
- puts "Removed annotation from: #{deannotated.join(', ')}"
459
+ puts "Removed annotations from: #{deannotated.join(', ')}"
412
460
  end
413
461
 
414
462
  def find_test_file(dir, file_name)
415
463
  Dir.glob(File.join(dir, "**", file_name)).first || File.join(dir, file_name)
416
464
  end
465
+
466
+ def resolve_filename(filename_template, model_name, table_name)
467
+ return filename_template.
468
+ gsub('%MODEL_NAME%', model_name).
469
+ gsub('%TABLE_NAME%', table_name || model_name.pluralize)
470
+ end
417
471
  end
418
472
  end