annotate 2.6.10 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d69e9ad0ab7a59e673f3cb7287d6cccb78b8ba20
4
+ data.tar.gz: a3b5adea28b4f3ebedc4f7af1df32907167d2bb9
5
+ SHA512:
6
+ metadata.gz: e6b5b503403df98d298e29c1ea4413999496d4c67326704c4c59a079bcd58fa3c6160e0e8812793a5e2796ddd8dcb216482793e5ff11e789463432c93d76cadd
7
+ data.tar.gz: 15d8f31b8c2bebd74cb0447b5f8283bf0397ae73b8e5a5fd6dc1306b19511cbbd03523338327da32fe2acc599c292fe2f0d434b5969b6eca2468d3bd2c4b9139
@@ -1,3 +1,6 @@
1
+ == 2.7.0
2
+ See https://github.com/ctran/annotate_models/releases/tag/v2.7.0
3
+
1
4
  == 2.6.9
2
5
  * Support foreigh key (#241)
3
6
  * Check if model has skip tag in annotate_model_file (#167)
@@ -51,7 +51,7 @@ Also, if you pass the -r option, it'll annotate routes.rb with the output of
51
51
 
52
52
  Into Gemfile from rubygems.org:
53
53
 
54
- gem 'annotate', '~> 2.6.6'
54
+ gem 'annotate'
55
55
 
56
56
  Into Gemfile from Github:
57
57
 
@@ -100,9 +100,7 @@ To remove routes.rb annotations:
100
100
 
101
101
  annotate --routes --delete
102
102
 
103
-
104
- == Configuration
105
-
103
+ To automatically annotate every time you run +db:migrate+, either run +rails g annotate:install+ or add +Annotate.load_tasks+ to your `Rakefile`. See the [configuration in Rails](#configuration-in-rails) section for more info.
106
104
 
107
105
  === Usage Outside of Rails
108
106
 
@@ -112,7 +110,6 @@ or more +--model-dir+ options to inform annotate about the structure of your
112
110
  project and help it bootstrap and load the relevant code.
113
111
 
114
112
 
115
-
116
113
  == Configuration
117
114
 
118
115
  If you want to always skip annotations on a particular model, add this string
@@ -130,7 +127,13 @@ default options:
130
127
  Edit this file to control things like output format, where annotations are
131
128
  added (top or bottom of file), and in which artifacts.
132
129
 
133
- == Rails Integration
130
+ The generated rakefile +lib/tasks/auto_annotate_models.rake+ also contains
131
+ `Annotate.load_tasks`. This adds a few rake tasks which duplicate command-line
132
+ functionality:
133
+
134
+ rake annotate_models # Add schema information (as comments) to model and fixture files
135
+ rake annotate_routes # Adds the route map to routes.rb
136
+ rake remove_annotation # Remove schema information from model and fixture files
134
137
 
135
138
  By default, once you've generated a configuration file, annotate will be
136
139
  executed whenever you run +rake db:migrate+ (but only in development mode).
@@ -27,13 +27,13 @@ Gem::Specification.new do |s|
27
27
 
28
28
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
29
29
  s.add_runtime_dependency(%q<rake>, ["~> 10.4"])
30
- s.add_runtime_dependency(%q<activerecord>, [">= 3.2", "<= 4.3"])
30
+ s.add_runtime_dependency(%q<activerecord>, [">= 3.2", "< 6.0"])
31
31
  else
32
32
  s.add_dependency(%q<rake>, ["~> 10.4"])
33
- s.add_dependency(%q<activerecord>, [">= 3.2", "<= 4.3"])
33
+ s.add_dependency(%q<activerecord>, [">= 3.2", "< 6.0"])
34
34
  end
35
35
  else
36
36
  s.add_dependency(%q<rake>, [">= 0.8.7"])
37
- s.add_dependency(%q<activerecord>, [">= 3.2", "<= 4.3"])
37
+ s.add_dependency(%q<activerecord>, [">= 3.2", "< 6.0"])
38
38
  end
39
39
  end
@@ -18,18 +18,16 @@ require 'optparse'
18
18
  require 'annotate'
19
19
  Annotate.bootstrap_rake
20
20
 
21
- target = {
22
- :klass => AnnotateModels,
23
- :task => :do_annotations,
24
- }
25
21
  has_set_position = {}
22
+ target_action = :do_annotations
23
+
26
24
  OptionParser.new do |opts|
27
25
  opts.banner = "Usage: annotate [options] [model_file]*"
28
26
 
29
27
  opts.on('-d', '--delete',
30
28
  "Remove annotations from all model files or the routes.rb file") do
31
29
 
32
- target[:task] = :remove_annotations
30
+ target_action = :remove_annotations
33
31
  end
34
32
 
35
33
  opts.on('-p', '--position [before|top|after|bottom]', ['before', 'top', 'after', 'bottom'],
@@ -93,10 +91,7 @@ OptionParser.new do |opts|
93
91
 
94
92
  opts.on('-r', '--routes',
95
93
  "Annotate routes.rb with the output of 'rake routes'") do
96
- target = {
97
- :klass => AnnotateRoutes,
98
- :task => :do_annotations
99
- }
94
+ ENV['routes'] = 'true'
100
95
  end
101
96
 
102
97
  opts.on('-v', '--version',
@@ -129,6 +124,11 @@ OptionParser.new do |opts|
129
124
  ENV['model_dir'] = dir
130
125
  end
131
126
 
127
+ opts.on('--root-dir dir',
128
+ "Annotate files stored within root dir projects, separate multiple dirs with comas") do |dir|
129
+ ENV['root_dir'] = dir
130
+ end
131
+
132
132
  opts.on('--ignore-model-subdirects',
133
133
  "Ignore subdirectories of the models directory") do |dir|
134
134
  ENV['ignore_model_sub_dir'] = "yes"
@@ -178,8 +178,18 @@ OptionParser.new do |opts|
178
178
  ENV['ignore_columns'] = regex
179
179
  end
180
180
 
181
+ opts.on('--hide-limit-column-types VALUES', "don't show limit for given column types, separated by comas (i.e., `integer,boolean,text`)" ) do |values|
182
+ ENV['hide_limit_column_types'] = "#{values}"
183
+ end
184
+
185
+ opts.on('--ignore-unknown-models', "don't display warnings for bad model files" ) do |values|
186
+ ENV['ignore_unknown_models'] = "true"
187
+ end
188
+
181
189
  end.parse!
182
190
 
183
191
  options = Annotate.setup_options({ :is_rake => ENV['is_rake'] && !ENV['is_rake'].empty? })
184
192
  Annotate.eager_load(options)
185
- target[:klass].send(target[:task], options)
193
+
194
+ AnnotateModels.send(target_action, options) if Annotate.include_models?
195
+ AnnotateRoutes.send(target_action, options) if Annotate.include_routes?
@@ -7,7 +7,7 @@ begin
7
7
  # ActiveSupport 3.x...
8
8
  require 'active_support/hash_with_indifferent_access'
9
9
  require 'active_support/core_ext/object/blank'
10
- rescue Exception => e
10
+ rescue Exception
11
11
  # ActiveSupport 2.x...
12
12
  require 'active_support/core_ext/hash/indifferent_access'
13
13
  require 'active_support/core_ext/blank'
@@ -27,32 +27,36 @@ module Annotate
27
27
  :exclude_fixtures, :exclude_factories, :ignore_model_sub_dir,
28
28
  :format_bare, :format_rdoc, :format_markdown, :sort, :force, :trace,
29
29
  :timestamp, :exclude_serializers, :classified_sort, :show_foreign_keys,
30
+ :exclude_scaffolds, :exclude_controllers, :exclude_helpers, :ignore_unknown_models,
30
31
  ]
31
32
  OTHER_OPTIONS=[
32
- :ignore_columns
33
+ :ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close, :wrapper, :routes,
34
+ :hide_limit_column_types,
33
35
  ]
34
36
  PATH_OPTIONS=[
35
- :require, :model_dir
37
+ :require, :model_dir, :root_dir
36
38
  ]
37
39
 
38
-
39
40
  ##
40
41
  # Set default values that can be overridden via environment variables.
41
42
  #
42
43
  def self.set_defaults(options = {})
43
44
  return if(@has_set_defaults)
44
45
  @has_set_defaults = true
46
+
45
47
  options = HashWithIndifferentAccess.new(options)
48
+
46
49
  [POSITION_OPTIONS, FLAG_OPTIONS, PATH_OPTIONS, OTHER_OPTIONS].flatten.each do |key|
47
- if(options.has_key?(key))
48
- default_value = if(options[key].is_a?(Array))
50
+ if options.has_key?(key)
51
+ default_value = if options[key].is_a?(Array)
49
52
  options[key].join(",")
50
53
  else
51
54
  options[key]
52
55
  end
53
56
  end
54
- default_value = ENV[key.to_s] if(!ENV[key.to_s].blank?)
55
- ENV[key.to_s] = default_value.to_s
57
+
58
+ default_value = ENV[key.to_s] if !ENV[key.to_s].blank?
59
+ ENV[key.to_s] = default_value.nil? ? nil : default_value.to_s
56
60
  end
57
61
  end
58
62
 
@@ -75,13 +79,34 @@ module Annotate
75
79
  options[:model_dir] = ['app/models']
76
80
  end
77
81
 
82
+ if(options[:root_dir].empty?)
83
+ options[:root_dir] = ['']
84
+ end
85
+
86
+ options[:wrapper_open] ||= options[:wrapper]
87
+ options[:wrapper_close] ||= options[:wrapper]
88
+
78
89
  return options
79
90
  end
80
91
 
92
+ def self.reset_options
93
+ [POSITION_OPTIONS, FLAG_OPTIONS, PATH_OPTIONS, OTHER_OPTIONS].flatten.each do |key|
94
+ ENV[key.to_s] = nil
95
+ end
96
+ end
97
+
81
98
  def self.skip_on_migration?
82
99
  ENV['skip_on_db_migrate'] =~ TRUE_RE
83
100
  end
84
101
 
102
+ def self.include_routes?
103
+ ENV['routes'] =~ TRUE_RE
104
+ end
105
+
106
+ def self.include_models?
107
+ true
108
+ end
109
+
85
110
  def self.loaded_tasks=(val); @loaded_tasks = val; end
86
111
  def self.loaded_tasks; return @loaded_tasks; end
87
112
 
@@ -124,7 +149,7 @@ module Annotate
124
149
  def self.bootstrap_rake
125
150
  begin
126
151
  require 'rake/dsl_definition'
127
- rescue Exception => e
152
+ rescue Exception
128
153
  # We might just be on an old version of Rake...
129
154
  end
130
155
  require 'rake'
@@ -9,6 +9,8 @@ module AnnotateModels
9
9
  END_MARK = "== Schema Information End"
10
10
  PATTERN = /^\r?\n?# (?:#{COMPAT_PREFIX}|#{COMPAT_PREFIX_MD}).*?\r?\n(#.*\r?\n)*(\r?\n)*/
11
11
 
12
+ MATCHED_TYPES = %w(test fixture factory serializer scaffold controller helper)
13
+
12
14
  # File.join for windows reverse bar compat?
13
15
  # I dont use windows, can`t test
14
16
  UNIT_TEST_DIR = File.join("test", "unit")
@@ -17,6 +19,12 @@ module AnnotateModels
17
19
  FIXTURE_TEST_DIR = File.join("test", "fixtures")
18
20
  FIXTURE_SPEC_DIR = File.join("spec", "fixtures")
19
21
 
22
+ # Other test files
23
+ CONTROLLER_TEST_DIR = File.join("test", "controllers")
24
+ CONTROLLER_SPEC_DIR = File.join("spec", "controllers")
25
+ REQUEST_SPEC_DIR = File.join("spec", "requests")
26
+ ROUTING_SPEC_DIR = File.join("spec", "routing")
27
+
20
28
  # Object Daddy http://github.com/flogic/object_daddy/tree/master
21
29
  EXEMPLARS_TEST_DIR = File.join("test", "exemplars")
22
30
  EXEMPLARS_SPEC_DIR = File.join("spec", "exemplars")
@@ -38,36 +46,11 @@ module AnnotateModels
38
46
  SERIALIZERS_TEST_DIR = File.join("test", "serializers")
39
47
  SERIALIZERS_SPEC_DIR = File.join("spec", "serializers")
40
48
 
49
+ # Controller files
50
+ CONTROLLER_DIR = File.join("app", "controllers")
41
51
 
42
- TEST_PATTERNS = [
43
- File.join(UNIT_TEST_DIR, "%MODEL_NAME%_test.rb"),
44
- File.join(MODEL_TEST_DIR, "%MODEL_NAME%_test.rb"),
45
- File.join(SPEC_MODEL_DIR, "%MODEL_NAME%_spec.rb"),
46
- ]
47
-
48
- FIXTURE_PATTERNS = [
49
- File.join(FIXTURE_TEST_DIR, "%TABLE_NAME%.yml"),
50
- File.join(FIXTURE_SPEC_DIR, "%TABLE_NAME%.yml"),
51
- ]
52
-
53
- FACTORY_PATTERNS = [
54
- File.join(EXEMPLARS_TEST_DIR, "%MODEL_NAME%_exemplar.rb"),
55
- File.join(EXEMPLARS_SPEC_DIR, "%MODEL_NAME%_exemplar.rb"),
56
- File.join(BLUEPRINTS_TEST_DIR, "%MODEL_NAME%_blueprint.rb"),
57
- File.join(BLUEPRINTS_SPEC_DIR, "%MODEL_NAME%_blueprint.rb"),
58
- File.join(FACTORY_GIRL_TEST_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
59
- File.join(FACTORY_GIRL_SPEC_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
60
- File.join(FACTORY_GIRL_TEST_DIR, "%TABLE_NAME%.rb"), # (new style)
61
- File.join(FACTORY_GIRL_SPEC_DIR, "%TABLE_NAME%.rb"), # (new style)
62
- File.join(FABRICATORS_TEST_DIR, "%MODEL_NAME%_fabricator.rb"),
63
- File.join(FABRICATORS_SPEC_DIR, "%MODEL_NAME%_fabricator.rb"),
64
- ]
65
-
66
- SERIALIZER_PATTERNS = [
67
- File.join(SERIALIZERS_DIR, "%MODEL_NAME%_serializer.rb"),
68
- File.join(SERIALIZERS_TEST_DIR, "%MODEL_NAME%_serializer_spec.rb"),
69
- File.join(SERIALIZERS_SPEC_DIR, "%MODEL_NAME%_serializer_spec.rb")
70
- ]
52
+ # Helper files
53
+ HELPER_DIR = File.join("app", "helpers")
71
54
 
72
55
  # Don't show limit (#) on these column types
73
56
  # Example: show "integer" instead of "integer(4)"
@@ -82,6 +65,72 @@ module AnnotateModels
82
65
  @model_dir = dir
83
66
  end
84
67
 
68
+ def root_dir
69
+ @root_dir.is_a?(Array) ? @root_dir : [@root_dir || ""]
70
+ end
71
+
72
+ def root_dir=(dir)
73
+ @root_dir = dir
74
+ end
75
+
76
+ def get_patterns(pattern_types=MATCHED_TYPES)
77
+ current_patterns = []
78
+ root_dir.each do |root_directory|
79
+ Array(pattern_types).each do |pattern_type|
80
+ current_patterns += case pattern_type
81
+ when 'test'
82
+ [
83
+ File.join(root_directory, UNIT_TEST_DIR, "%MODEL_NAME%_test.rb"),
84
+ File.join(root_directory, MODEL_TEST_DIR, "%MODEL_NAME%_test.rb"),
85
+ File.join(root_directory, SPEC_MODEL_DIR, "%MODEL_NAME%_spec.rb"),
86
+ ]
87
+ when 'fixture'
88
+ [
89
+ File.join(root_directory, FIXTURE_TEST_DIR, "%TABLE_NAME%.yml"),
90
+ File.join(root_directory, FIXTURE_SPEC_DIR, "%TABLE_NAME%.yml"),
91
+ File.join(root_directory, FIXTURE_TEST_DIR, "%PLURALIZED_MODEL_NAME%.yml"),
92
+ File.join(root_directory, FIXTURE_SPEC_DIR, "%PLURALIZED_MODEL_NAME%.yml"),
93
+ ]
94
+ when 'scaffold'
95
+ [
96
+ File.join(root_directory, CONTROLLER_TEST_DIR, "%PLURALIZED_MODEL_NAME%_controller_test.rb"),
97
+ File.join(root_directory, CONTROLLER_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_controller_spec.rb"),
98
+ File.join(root_directory, REQUEST_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_spec.rb"),
99
+ File.join(root_directory, ROUTING_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_routing_spec.rb"),
100
+ ]
101
+ when 'factory'
102
+ [
103
+ File.join(root_directory, EXEMPLARS_TEST_DIR, "%MODEL_NAME%_exemplar.rb"),
104
+ File.join(root_directory, EXEMPLARS_SPEC_DIR, "%MODEL_NAME%_exemplar.rb"),
105
+ File.join(root_directory, BLUEPRINTS_TEST_DIR, "%MODEL_NAME%_blueprint.rb"),
106
+ File.join(root_directory, BLUEPRINTS_SPEC_DIR, "%MODEL_NAME%_blueprint.rb"),
107
+ File.join(root_directory, FACTORY_GIRL_TEST_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
108
+ File.join(root_directory, FACTORY_GIRL_SPEC_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
109
+ File.join(root_directory, FACTORY_GIRL_TEST_DIR, "%TABLE_NAME%.rb"), # (new style)
110
+ File.join(root_directory, FACTORY_GIRL_SPEC_DIR, "%TABLE_NAME%.rb"), # (new style)
111
+ File.join(root_directory, FABRICATORS_TEST_DIR, "%MODEL_NAME%_fabricator.rb"),
112
+ File.join(root_directory, FABRICATORS_SPEC_DIR, "%MODEL_NAME%_fabricator.rb"),
113
+ ]
114
+ when 'serializer'
115
+ [
116
+ File.join(root_directory, SERIALIZERS_DIR, "%MODEL_NAME%_serializer.rb"),
117
+ File.join(root_directory, SERIALIZERS_TEST_DIR, "%MODEL_NAME%_serializer_spec.rb"),
118
+ File.join(root_directory, SERIALIZERS_SPEC_DIR, "%MODEL_NAME%_serializer_spec.rb")
119
+ ]
120
+ when 'controller'
121
+ [
122
+ File.join(root_directory, CONTROLLER_DIR, "%PLURALIZED_MODEL_NAME%_controller.rb")
123
+ ]
124
+ when 'helper'
125
+ [
126
+ File.join(root_directory, HELPER_DIR, "%PLURALIZED_MODEL_NAME%_helper.rb")
127
+ ]
128
+ end
129
+ end
130
+ end
131
+ current_patterns.map{ |p| p.sub(/^[\/]*/, '') }
132
+ end
133
+
85
134
  # Simple quoting for the default column value
86
135
  def quote(value)
87
136
  case value
@@ -91,6 +140,7 @@ module AnnotateModels
91
140
  when Float, Fixnum, Bignum then value.to_s
92
141
  # BigDecimals need to be output in a non-normalized form and quoted.
93
142
  when BigDecimal then value.to_s('F')
143
+ when Array then value.map {|v| quote(v)}
94
144
  else
95
145
  value.inspect
96
146
  end
@@ -127,20 +177,24 @@ module AnnotateModels
127
177
  info<< "# #{ '-' * ( max_size + md_names_overhead ) } | #{'-' * md_type_allowance} | #{ '-' * 27 }\n"
128
178
  end
129
179
 
130
- cols = klass.columns
131
- if options[:ignore_columns]
132
- cols.reject! { |col| col.name.match(/#{options[:ignore_columns]}/) }
133
- end
180
+ cols = if ignore_columns = options[:ignore_columns]
181
+ klass.columns.reject do |col|
182
+ col.name.match(/#{ignore_columns}/)
183
+ end
184
+ else
185
+ klass.columns
186
+ end
134
187
 
135
188
  cols = cols.sort_by(&:name) if(options[:sort])
136
189
  cols = classified_sort(cols) if(options[:classified_sort])
137
190
  cols.each do |col|
191
+ col_type = (col.type || col.sql_type).to_s
192
+
138
193
  attrs = []
139
- attrs << "default(#{schema_default(klass, col)})" unless col.default.nil?
194
+ attrs << "default(#{schema_default(klass, col)})" unless col.default.nil? || col_type == "jsonb"
140
195
  attrs << "not null" unless col.null
141
196
  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)
142
197
 
143
- col_type = (col.type || col.sql_type).to_s
144
198
  if col_type == "decimal"
145
199
  col_type << "(#{col.precision}, #{col.scale})"
146
200
  elsif col_type != "spatial"
@@ -148,7 +202,7 @@ module AnnotateModels
148
202
  if col.limit.is_a? Array
149
203
  attrs << "(#{col.limit.join(', ')})"
150
204
  else
151
- col_type << "(#{col.limit})" unless NO_LIMIT_COL_TYPES.include?(col_type)
205
+ col_type << "(#{col.limit})" unless hide_limit?(col_type, options)
152
206
  end
153
207
  end
154
208
  end
@@ -227,6 +281,17 @@ module AnnotateModels
227
281
  return index_info
228
282
  end
229
283
 
284
+ def hide_limit?(col_type, options)
285
+ excludes =
286
+ if options[:hide_limit_column_types].blank?
287
+ NO_LIMIT_COL_TYPES
288
+ else
289
+ options[:hide_limit_column_types].split(',')
290
+ end
291
+
292
+ excludes.include?(col_type)
293
+ end
294
+
230
295
  def get_foreign_key_info(klass, options={})
231
296
  if(options[:format_markdown])
232
297
  fk_info = "#\n# ### Foreign Keys\n#\n"
@@ -234,7 +299,9 @@ module AnnotateModels
234
299
  fk_info = "#\n# Foreign Keys\n#\n"
235
300
  end
236
301
 
237
- foreign_keys = klass.connection.respond_to?(:foreign_keys) ? klass.connection.foreign_keys(klass.table_name) : []
302
+ return "" unless klass.connection.supports_foreign_keys? && klass.connection.respond_to?(:foreign_keys)
303
+
304
+ foreign_keys = klass.connection.foreign_keys(klass.table_name)
238
305
  return "" if foreign_keys.empty?
239
306
 
240
307
  max_size = foreign_keys.collect{|fk| fk.name.size}.max + 1
@@ -274,8 +341,8 @@ module AnnotateModels
274
341
  old_columns = old_header && old_header.scan(column_pattern).sort
275
342
  new_columns = new_header && new_header.scan(column_pattern).sort
276
343
 
277
- encoding = Regexp.new(/(^#\s*encoding:.*\n)|(^# coding:.*\n)|(^# -\*- coding:.*\n)|(^# -\*- encoding\s?:.*\n)/)
278
- encoding_header = old_content.match(encoding).to_s
344
+ magic_comment_matcher= Regexp.new(/(^#\s*encoding:.*\n)|(^# coding:.*\n)|(^# -\*- coding:.*\n)|(^# -\*- encoding\s?:.*\n)|(^#\s*frozen_string_literal:.+\n)|(^# -\*- frozen_string_literal\s*:.+-\*-\n)/)
345
+ magic_comments= old_content.scan(magic_comment_matcher).flatten.compact
279
346
 
280
347
  if old_columns == new_columns && !options[:force]
281
348
  return false
@@ -288,17 +355,17 @@ module AnnotateModels
288
355
  end
289
356
 
290
357
  wrapper_open = options[:wrapper_open] ? "# #{options[:wrapper_open]}\n" : ""
291
- wrapper_close = options[:wrapper_close] ? "\n# #{options[:wrapper_close]}" : ""
358
+ wrapper_close = options[:wrapper_close] ? "# #{options[:wrapper_close]}\n" : ""
292
359
  wrapped_info_block = "#{wrapper_open}#{info_block}#{wrapper_close}"
293
360
  # if there *was* no old schema info (no substitution happened) or :force was passed,
294
361
  # we simply need to insert it in correct position
295
362
  if new_content == old_content || options[:force]
296
- old_content.sub!(encoding, '')
363
+ old_content.sub!(magic_comment_matcher, '')
297
364
  old_content.sub!(PATTERN, '')
298
365
 
299
366
  new_content = %w(after bottom).include?(options[position].to_s) ?
300
- (encoding_header + (old_content.rstrip + "\n\n" + wrapped_info_block)) :
301
- (encoding_header + wrapped_info_block + "\n" + old_content)
367
+ (magic_comments.join + (old_content.rstrip + "\n\n" + wrapped_info_block)) :
368
+ (magic_comments.join + wrapped_info_block + "\n" + old_content)
302
369
  end
303
370
 
304
371
  File.open(file_name, "wb") { |f| f.puts new_content }
@@ -340,6 +407,9 @@ module AnnotateModels
340
407
  # :exclude_fixtures<Symbol>:: whether to skip modification of fixture files
341
408
  # :exclude_factories<Symbol>:: whether to skip modification of factory files
342
409
  # :exclude_serializers<Symbol>:: whether to skip modification of serializer files
410
+ # :exclude_scaffolds<Symbol>:: whether to skip modification of scaffold files
411
+ # :exclude_controllers<Symbol>:: whether to skip modification of controller files
412
+ # :exclude_helpers<Symbol>:: whether to skip modification of helper files
343
413
  #
344
414
  def annotate(klass, file, header, options={})
345
415
  begin
@@ -353,15 +423,14 @@ module AnnotateModels
353
423
  did_annotate = true
354
424
  end
355
425
 
356
- %w(test fixture factory serializer).each do |key|
426
+ MATCHED_TYPES.each do |key|
357
427
  exclusion_key = "exclude_#{key.pluralize}".to_sym
358
- patterns_constant = "#{key.upcase}_PATTERNS".to_sym
359
428
  position_key = "position_in_#{key}".to_sym
360
429
 
361
430
  unless options[exclusion_key]
362
- did_annotate = self.const_get(patterns_constant).
363
- map { |file| resolve_filename(file, model_name, table_name) }.
364
- map { |file| annotate_one_file(file, info, position_key, options_with_position(options, position_key)) }.
431
+ did_annotate = self.get_patterns(key).
432
+ map { |f| resolve_filename(f, model_name, table_name) }.
433
+ map { |f| annotate_one_file(f, info, position_key, options_with_position(options, position_key)) }.
365
434
  detect { |result| result } || did_annotate
366
435
  end
367
436
  end
@@ -419,11 +488,11 @@ module AnnotateModels
419
488
  model_path = file.gsub(/\.rb$/, '')
420
489
  model_dir.each { |dir| model_path = model_path.gsub(/^#{dir}/, '').gsub(/^\//, '') }
421
490
  begin
422
- get_loaded_model(model_path) or raise LoadError.new("cannot load a model from #{file}")
491
+ get_loaded_model(model_path) or raise BadModelFileError.new
423
492
  rescue LoadError
424
493
  # this is for non-rails projects, which don't get Rails auto-require magic
425
494
  file_path = File.expand_path(file)
426
- if File.file?(file_path) && Kernel.require(file_path)
495
+ if File.file?(file_path) && silence_warnings { Kernel.require(file_path) }
427
496
  retry
428
497
  elsif model_path.match(/\//)
429
498
  model_path = model_path.split('/')[1..-1].join('/').to_s
@@ -465,13 +534,14 @@ module AnnotateModels
465
534
  end
466
535
 
467
536
  self.model_dir = options[:model_dir] if options[:model_dir]
537
+ self.root_dir = options[:root_dir] if options[:root_dir]
468
538
 
469
539
  annotated = []
470
540
  get_model_files(options).each do |file|
471
541
  annotate_model_file(annotated, File.join(file), header, options)
472
542
  end
473
543
  if annotated.empty?
474
- puts "Nothing to annotate."
544
+ puts "Model files unchanged."
475
545
  else
476
546
  puts "Annotated (#{annotated.length}): #{annotated.join(', ')}"
477
547
  end
@@ -483,9 +553,14 @@ module AnnotateModels
483
553
  klass = get_model_class(file)
484
554
  if klass && klass < ActiveRecord::Base && !klass.abstract_class? && klass.table_exists?
485
555
  if annotate(klass, file, header, options)
486
- annotated << klass
556
+ annotated << file
487
557
  end
488
558
  end
559
+ rescue BadModelFileError => e
560
+ unless options[:ignore_unknown_models]
561
+ puts "Unable to annotate #{file}: #{e.message}"
562
+ puts "\t" + e.backtrace.join("\n\t") if options[:trace]
563
+ end
489
564
  rescue Exception => e
490
565
  puts "Unable to annotate #{file}: #{e.message}"
491
566
  puts "\t" + e.backtrace.join("\n\t") if options[:trace]
@@ -494,6 +569,7 @@ module AnnotateModels
494
569
 
495
570
  def remove_annotations(options={})
496
571
  self.model_dir = options[:model_dir] if options[:model_dir]
572
+ self.root_dir = options[:root_dir] if options[:root_dir]
497
573
  deannotated = []
498
574
  deannotated_klass = false
499
575
  get_model_files(options).each do |file|
@@ -506,11 +582,11 @@ module AnnotateModels
506
582
  model_file_name = file
507
583
  deannotated_klass = true if(remove_annotation_of_file(model_file_name))
508
584
 
509
- (TEST_PATTERNS + FIXTURE_PATTERNS + FACTORY_PATTERNS + SERIALIZER_PATTERNS).
510
- map { |file| resolve_filename(file, model_name, table_name) }.
511
- each do |file|
512
- if File.exist?(file)
513
- remove_annotation_of_file(file)
585
+ get_patterns.
586
+ map { |f| resolve_filename(f, model_name, table_name) }.
587
+ each do |f|
588
+ if File.exist?(f)
589
+ remove_annotation_of_file(f)
514
590
  deannotated_klass = true
515
591
  end
516
592
  end
@@ -527,6 +603,7 @@ module AnnotateModels
527
603
  def resolve_filename(filename_template, model_name, table_name)
528
604
  return filename_template.
529
605
  gsub('%MODEL_NAME%', model_name).
606
+ gsub('%PLURALIZED_MODEL_NAME%', model_name.pluralize).
530
607
  gsub('%TABLE_NAME%', table_name || model_name.pluralize)
531
608
  end
532
609
 
@@ -551,5 +628,19 @@ module AnnotateModels
551
628
 
552
629
  return ([id] << rest_cols << timestamps << associations).flatten
553
630
  end
631
+
632
+ # Ignore warnings for the duration of the block ()
633
+ def silence_warnings
634
+ old_verbose, $VERBOSE = $VERBOSE, nil
635
+ yield
636
+ ensure
637
+ $VERBOSE = old_verbose
638
+ end
639
+ end
640
+
641
+ class BadModelFileError < LoadError
642
+ def to_s
643
+ "file doesn't contain a valid model class"
644
+ end
554
645
  end
555
646
  end
@@ -37,7 +37,8 @@ module AnnotateRoutes
37
37
  "#"
38
38
  ] + routes_map.map { |line| "# #{line}".rstrip }
39
39
 
40
- (content, where_header_found) = strip_annotations(File.read(routes_file))
40
+ existing_text = File.read(routes_file)
41
+ (content, where_header_found) = strip_annotations(existing_text)
41
42
  changed = where_header_found != 0 # This will either be :before, :after, or
42
43
  # a number. If the number is > 0, the
43
44
  # annotation was found somewhere in the
@@ -60,21 +61,25 @@ module AnnotateRoutes
60
61
 
61
62
  content = position_after ? (content + header) : header + content
62
63
 
63
- write_contents(content)
64
-
65
- puts "Route file annotated."
64
+ if write_contents(existing_text, content)
65
+ puts "#{routes_file} annotated."
66
+ else
67
+ puts "#{routes_file} unchanged."
68
+ end
66
69
  end
67
70
 
68
71
  def self.remove_annotations(options={})
69
72
  return unless(routes_exists?)
70
-
71
- (content, where_header_found) = strip_annotations(File.read(routes_file))
73
+ existing_text = File.read(routes_file)
74
+ (content, where_header_found) = strip_annotations(existing_text)
72
75
 
73
76
  content = strip_on_removal(content, where_header_found)
74
77
 
75
- write_contents(content)
76
-
77
- puts "Removed annotations from routes file."
78
+ if write_contents(existing_text, content)
79
+ puts "Removed annotations from #{routes_file}."
80
+ else
81
+ puts "#{routes_file} unchanged."
82
+ end
78
83
  end
79
84
 
80
85
  protected
@@ -89,11 +94,15 @@ protected
89
94
  return routes_exists
90
95
  end
91
96
 
92
- def self.write_contents(content)
93
- content << '' unless(content.last == '') # Make sure we end on a trailing
94
- # newline.
97
+ def self.write_contents(existing_text, new_content)
98
+ # Make sure we end on a trailing newline.
99
+ new_content << '' unless(new_content.last == '')
100
+ new_text = new_content.join("\n")
101
+
102
+ return false if existing_text == new_text
95
103
 
96
- File.open(routes_file, "wb") { |f| f.puts(content.join("\n")) }
104
+ File.open(routes_file, "wb") { |f| f.puts(new_text) }
105
+ return true
97
106
  end
98
107
 
99
108
  def self.strip_annotations(content)
@@ -1,5 +1,5 @@
1
1
  module Annotate
2
2
  def self.version
3
- '2.6.10'
3
+ '2.7.0'
4
4
  end
5
5
  end
@@ -5,32 +5,42 @@ if Rails.env.development?
5
5
  task :set_annotation_options do
6
6
  # You can override any of these by setting an environment variable of the
7
7
  # same name.
8
- Annotate.set_defaults({
9
- 'position_in_routes' => "before",
10
- 'position_in_class' => "before",
11
- 'position_in_test' => "before",
12
- 'position_in_fixture' => "before",
13
- 'position_in_factory' => "before",
14
- 'position_in_serializer' => "before",
15
- 'show_foreign_keys' => "true",
16
- 'show_indexes' => "true",
17
- 'simple_indexes' => "false",
18
- 'model_dir' => "app/models",
19
- 'include_version' => "false",
20
- 'require' => "",
21
- 'exclude_tests' => "false",
22
- 'exclude_fixtures' => "false",
23
- 'exclude_factories' => "false",
24
- 'exclude_serializers' => "false",
25
- 'ignore_model_sub_dir' => "false",
26
- 'skip_on_db_migrate' => "false",
27
- 'format_bare' => "true",
28
- 'format_rdoc' => "false",
29
- 'format_markdown' => "false",
30
- 'sort' => "false",
31
- 'force' => "false",
32
- 'trace' => "false",
33
- })
8
+ Annotate.set_defaults(
9
+ 'routes' => 'false',
10
+ 'position_in_routes' => 'before',
11
+ 'position_in_class' => 'before',
12
+ 'position_in_test' => 'before',
13
+ 'position_in_fixture' => 'before',
14
+ 'position_in_factory' => 'before',
15
+ 'position_in_serializer' => 'before',
16
+ 'show_foreign_keys' => 'true',
17
+ 'show_indexes' => 'true',
18
+ 'simple_indexes' => 'false',
19
+ 'model_dir' => 'app/models',
20
+ 'root_dir' => '',
21
+ 'include_version' => 'false',
22
+ 'require' => '',
23
+ 'exclude_tests' => 'false',
24
+ 'exclude_fixtures' => 'false',
25
+ 'exclude_factories' => 'false',
26
+ 'exclude_serializers' => 'false',
27
+ 'exclude_scaffolds' => 'false',
28
+ 'exclude_controllers' => 'false',
29
+ 'exclude_helpers' => 'false',
30
+ 'ignore_model_sub_dir' => 'false',
31
+ 'ignore_columns' => nil,
32
+ 'ignore_unknown_models' => 'false',
33
+ 'hide_limit_column_types' => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(',') %>',
34
+ 'skip_on_db_migrate' => 'false',
35
+ 'format_bare' => 'true',
36
+ 'format_rdoc' => 'false',
37
+ 'format_markdown' => 'false',
38
+ 'sort' => 'false',
39
+ 'force' => 'false',
40
+ 'trace' => 'false',
41
+ 'wrapper_open' => nil,
42
+ 'wrapper_close' => nil,
43
+ )
34
44
  end
35
45
 
36
46
  Annotate.load_tasks
@@ -1,6 +1,6 @@
1
1
  annotate_lib = File.expand_path(File.dirname(File.dirname(__FILE__)))
2
2
 
3
- if(!ENV['is_cli'])
3
+ if !ENV['is_cli']
4
4
  task :set_annotation_options
5
5
  task :annotate_models => :set_annotation_options
6
6
  end
@@ -17,15 +17,20 @@ task :annotate_models => :environment do
17
17
  options[:position_in_factory] = Annotate.fallback(ENV['position_in_factory'], ENV['position'])
18
18
  options[:position_in_test] = Annotate.fallback(ENV['position_in_test'], ENV['position'])
19
19
  options[:position_in_serializer] = Annotate.fallback(ENV['position_in_serializer'], ENV['position'])
20
+ options[:show_foreign_keys] = Annotate.true?(ENV['show_foreign_keys'])
20
21
  options[:show_indexes] = Annotate.true?(ENV['show_indexes'])
21
22
  options[:simple_indexes] = Annotate.true?(ENV['simple_indexes'])
22
- options[:model_dir] = ENV['model_dir'] ? ENV['model_dir'].split(',') : []
23
+ options[:model_dir] = ENV['model_dir'] ? ENV['model_dir'].split(',') : ['app/models']
24
+ options[:root_dir] = ENV['root_dir'] ? ENV['root_dir'].split(',') : ['']
23
25
  options[:include_version] = Annotate.true?(ENV['include_version'])
24
26
  options[:require] = ENV['require'] ? ENV['require'].split(',') : []
25
27
  options[:exclude_tests] = Annotate.true?(ENV['exclude_tests'])
26
28
  options[:exclude_factories] = Annotate.true?(ENV['exclude_factories'])
27
29
  options[:exclude_fixtures] = Annotate.true?(ENV['exclude_fixtures'])
28
30
  options[:exclude_serializers] = Annotate.true?(ENV['exclude_serializers'])
31
+ options[:exclude_scaffolds] = Annotate.true?(ENV['exclude_scaffolds'])
32
+ options[:exclude_controllers] = Annotate.true?(ENV['exclude_controllers'])
33
+ options[:exclude_helpers] = Annotate.true?(ENV['exclude_helpers'])
29
34
  options[:ignore_model_sub_dir] = Annotate.true?(ENV['ignore_model_sub_dir'])
30
35
  options[:format_bare] = Annotate.true?(ENV['format_bare'])
31
36
  options[:format_rdoc] = Annotate.true?(ENV['format_rdoc'])
@@ -36,6 +41,8 @@ task :annotate_models => :environment do
36
41
  options[:trace] = Annotate.true?(ENV['trace'])
37
42
  options[:wrapper_open] = Annotate.fallback(ENV['wrapper_open'], ENV['wrapper'])
38
43
  options[:wrapper_close] = Annotate.fallback(ENV['wrapper_close'], ENV['wrapper'])
44
+ options[:ignore_columns] = ENV.fetch('ignore_columns', nil)
45
+
39
46
  AnnotateModels.do_annotations(options)
40
47
  end
41
48
 
@@ -46,6 +53,7 @@ task :remove_annotation => :environment do
46
53
 
47
54
  options={ :is_rake => true }
48
55
  options[:model_dir] = ENV['model_dir']
56
+ options[:root_dir] = ENV['root_dir']
49
57
  options[:require] = ENV['require'] ? ENV['require'].split(',') : []
50
58
  options[:trace] = Annotate.true?(ENV['trace'])
51
59
  AnnotateModels.remove_annotations(options)
@@ -2,20 +2,23 @@
2
2
  # (They are not used to build annotate itself.)
3
3
 
4
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.
5
+ # run after doing db:migrate.
6
+
8
7
  namespace :db do
9
- task :migrate do
10
- Annotate::Migration.update_annotations
11
- end
8
+ [:migrate, :rollback].each do |cmd|
9
+ task cmd do
10
+ Rake::Task['set_annotation_options'].invoke
11
+ Annotate::Migration.update_annotations
12
+ end
12
13
 
13
- namespace :migrate do
14
- [:change, :up, :down, :reset, :redo].each do |t|
15
- task t do
16
- Annotate::Migration.update_annotations
14
+ namespace cmd do
15
+ [:change, :up, :down, :reset, :redo].each do |t|
16
+ task t do
17
+ Rake::Task['set_annotation_options'].invoke
18
+ Annotate::Migration.update_annotations
19
+ end
17
20
  end
18
- end
21
+ end
19
22
  end
20
23
  end
21
24
 
@@ -24,9 +27,25 @@ module Annotate
24
27
  @@working = false
25
28
 
26
29
  def self.update_annotations
27
- unless @@working || (ENV['skip_on_db_migrate'] =~ /(true|t|yes|y|1)$/i)
30
+ unless @@working || Annotate.skip_on_migration?
28
31
  @@working = true
29
- Rake::Task['annotate_models'].invoke
32
+
33
+ self.update_models if Annotate.include_models?
34
+ self.update_routes if Annotate.include_routes?
35
+ end
36
+ end
37
+
38
+ def self.update_models
39
+ if Rake::Task.task_defined?("annotate_models")
40
+ Rake::Task["annotate_models"].invoke
41
+ elsif Rake::Task.task_defined?("app:annotate_models")
42
+ Rake::Task["app:annotate_models"].invoke
43
+ end
44
+ end
45
+
46
+ def self.update_routes
47
+ if Rake::Task.task_defined?("annotate_routes")
48
+ Rake::Task["annotate_routes"].invoke
30
49
  end
31
50
  end
32
51
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: annotate
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.10
5
- prerelease:
4
+ version: 2.7.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Alex Chaffee
@@ -13,46 +12,42 @@ authors:
13
12
  autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
- date: 2015-05-22 00:00:00.000000000 Z
15
+ date: 2015-12-30 00:00:00.000000000 Z
17
16
  dependencies:
18
17
  - !ruby/object:Gem::Dependency
19
18
  name: rake
20
19
  requirement: !ruby/object:Gem::Requirement
21
- none: false
22
20
  requirements:
23
- - - ~>
21
+ - - "~>"
24
22
  - !ruby/object:Gem::Version
25
23
  version: '10.4'
26
24
  type: :runtime
27
25
  prerelease: false
28
26
  version_requirements: !ruby/object:Gem::Requirement
29
- none: false
30
27
  requirements:
31
- - - ~>
28
+ - - "~>"
32
29
  - !ruby/object:Gem::Version
33
30
  version: '10.4'
34
31
  - !ruby/object:Gem::Dependency
35
32
  name: activerecord
36
33
  requirement: !ruby/object:Gem::Requirement
37
- none: false
38
34
  requirements:
39
- - - ! '>='
35
+ - - ">="
40
36
  - !ruby/object:Gem::Version
41
37
  version: '3.2'
42
- - - <=
38
+ - - "<"
43
39
  - !ruby/object:Gem::Version
44
- version: '4.3'
40
+ version: '6.0'
45
41
  type: :runtime
46
42
  prerelease: false
47
43
  version_requirements: !ruby/object:Gem::Requirement
48
- none: false
49
44
  requirements:
50
- - - ! '>='
45
+ - - ">="
51
46
  - !ruby/object:Gem::Version
52
47
  version: '3.2'
53
- - - <=
48
+ - - "<"
54
49
  - !ruby/object:Gem::Version
55
- version: '4.3'
50
+ version: '6.0'
56
51
  description: Annotates Rails/ActiveRecord Models, routes, fixtures, and others based
57
52
  on the database schema.
58
53
  email:
@@ -91,25 +86,24 @@ files:
91
86
  homepage: http://github.com/ctran/annotate_models
92
87
  licenses:
93
88
  - Ruby
89
+ metadata: {}
94
90
  post_install_message:
95
91
  rdoc_options: []
96
92
  require_paths:
97
93
  - lib
98
94
  required_ruby_version: !ruby/object:Gem::Requirement
99
- none: false
100
95
  requirements:
101
- - - ! '>='
96
+ - - ">="
102
97
  - !ruby/object:Gem::Version
103
98
  version: 1.9.3
104
99
  required_rubygems_version: !ruby/object:Gem::Requirement
105
- none: false
106
100
  requirements:
107
- - - ! '>='
101
+ - - ">="
108
102
  - !ruby/object:Gem::Version
109
103
  version: '0'
110
104
  requirements: []
111
105
  rubyforge_project: annotate
112
- rubygems_version: 1.8.23.2
106
+ rubygems_version: 2.5.0
113
107
  signing_key:
114
108
  specification_version: 4
115
109
  summary: Annotates Rails Models, routes, fixtures, and others based on the database