annotate 2.6.10 → 2.7.0

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.
@@ -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