annotate 3.1.1 → 3.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14932a4a189792b68c9d85c63313d0d60322ca22fed18a7a4a00edd47348743a
4
- data.tar.gz: 351b61b7b3eac94f1ce6d8a86e1630bbbf6c0920cacfe46319163a86bc189887
3
+ metadata.gz: a49c914d3c2486e109b4a499b71fe905c8534e21b1d44cee15056a3066468e2e
4
+ data.tar.gz: 383445b9f5c13d02da7190a009ed974b5f88b41fe88f156814e743b4f7ec99d2
5
5
  SHA512:
6
- metadata.gz: a717f48aff793ea4566fca6919eb4fe85b1545fe93b0bece91c5a9507cbb87fe14aa35ac520e618e98f8db92fe11010a8fe8653802b25b83b24590467e5d64f1
7
- data.tar.gz: d13aab072e5e3901788f4aff809e08f3d28ac24cf0eed4187b0e5c0f98008f3c95a7553b58c4f50705f2f42729e96a05a57631356715953bb7d29531e4365fbd
6
+ metadata.gz: 70b926aba8e1ba91ccf506cfdabb94016efaaf788beaf6bdc0691fb6ad30edf57b794842f93f9860e1f82fa38c2934530e6fc0940f88ce4b47a909da8456ddd0
7
+ data.tar.gz: bf94c7d38b3a11ddc658947a7c1f2164854070a5707f56c148bcbdd5495b88c270ee0f0e587b07c0c421724b40059f110c808a8f3af90e68a86c5e249dfb1fa1
data/README.md CHANGED
@@ -104,8 +104,8 @@ Into environment gems from Github checkout:
104
104
 
105
105
  git clone https://github.com/ctran/annotate_models.git annotate_models
106
106
  cd annotate_models
107
- rake build
108
- gem install pkg/annotate-*.gem
107
+ rake gem
108
+ gem install dist/annotate-*.gem
109
109
 
110
110
  ## Usage
111
111
 
data/annotate.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.executables = ['annotate']
16
16
  s.extra_rdoc_files = ['README.md', 'CHANGELOG.md']
17
17
  s.files = `git ls-files -z LICENSE.txt *.md *.gemspec bin lib`.split("\x0")
18
- s.homepage = 'http://github.com/ctran/annotate_models'
18
+ s.homepage = 'https://github.com/ctran/annotate_models'
19
19
  s.licenses = ['Ruby']
20
20
  s.require_paths = ['lib']
21
21
  s.rubygems_version = '2.1.11'
@@ -23,7 +23,10 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.specification_version = 4 if s.respond_to? :specification_version
25
25
  s.add_runtime_dependency(%q<rake>, '>= 10.4', '< 14.0')
26
- s.add_runtime_dependency(%q<activerecord>, ['>= 3.2', '< 7.0'])
26
+ s.add_runtime_dependency(%q<activerecord>, ['>= 3.2', '< 8.0'])
27
27
 
28
- s.metadata = { "github_repo" => "ssh://github.com/ctran/annotate_models" }
28
+ s.metadata = {
29
+ "bug_tracker_uri" => "https://github.com/ctran/annotate_models/issues/",
30
+ "source_code_uri" => "https://github.com/ctran/annotate_models.git"
31
+ }
29
32
  end
@@ -0,0 +1,127 @@
1
+ module AnnotateModels
2
+ # This module provides module method to get file paths.
3
+ module FilePatterns
4
+ # Controller files
5
+ CONTROLLER_DIR = File.join('app', 'controllers')
6
+
7
+ # Active admin registry files
8
+ ACTIVEADMIN_DIR = File.join('app', 'admin')
9
+
10
+ # Helper files
11
+ HELPER_DIR = File.join('app', 'helpers')
12
+
13
+ # File.join for windows reverse bar compat?
14
+ # I dont use windows, can`t test
15
+ UNIT_TEST_DIR = File.join('test', 'unit')
16
+ MODEL_TEST_DIR = File.join('test', 'models') # since rails 4.0
17
+ SPEC_MODEL_DIR = File.join('spec', 'models')
18
+
19
+ FIXTURE_TEST_DIR = File.join('test', 'fixtures')
20
+ FIXTURE_SPEC_DIR = File.join('spec', 'fixtures')
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
+
28
+ # Object Daddy http://github.com/flogic/object_daddy/tree/master
29
+ EXEMPLARS_TEST_DIR = File.join('test', 'exemplars')
30
+ EXEMPLARS_SPEC_DIR = File.join('spec', 'exemplars')
31
+
32
+ # Machinist http://github.com/notahat/machinist
33
+ BLUEPRINTS_TEST_DIR = File.join('test', 'blueprints')
34
+ BLUEPRINTS_SPEC_DIR = File.join('spec', 'blueprints')
35
+
36
+ # Factory Bot https://github.com/thoughtbot/factory_bot
37
+ FACTORY_BOT_TEST_DIR = File.join('test', 'factories')
38
+ FACTORY_BOT_SPEC_DIR = File.join('spec', 'factories')
39
+
40
+ # Fabrication https://github.com/paulelliott/fabrication.git
41
+ FABRICATORS_TEST_DIR = File.join('test', 'fabricators')
42
+ FABRICATORS_SPEC_DIR = File.join('spec', 'fabricators')
43
+
44
+ # Serializers https://github.com/rails-api/active_model_serializers
45
+ SERIALIZERS_DIR = File.join('app', 'serializers')
46
+ SERIALIZERS_TEST_DIR = File.join('test', 'serializers')
47
+ SERIALIZERS_SPEC_DIR = File.join('spec', 'serializers')
48
+
49
+ class << self
50
+ def generate(root_directory, pattern_type, options)
51
+ case pattern_type
52
+ when 'test' then test_files(root_directory)
53
+ when 'fixture' then fixture_files(root_directory)
54
+ when 'scaffold' then scaffold_files(root_directory)
55
+ when 'factory' then factory_files(root_directory)
56
+ when 'serializer' then serialize_files(root_directory)
57
+ when 'additional_file_patterns'
58
+ [options[:additional_file_patterns] || []].flatten
59
+ when 'controller'
60
+ [File.join(root_directory, CONTROLLER_DIR, '%PLURALIZED_MODEL_NAME%_controller.rb')]
61
+ when 'admin'
62
+ [
63
+ File.join(root_directory, ACTIVEADMIN_DIR, '%MODEL_NAME%.rb'),
64
+ File.join(root_directory, ACTIVEADMIN_DIR, '%PLURALIZED_MODEL_NAME%.rb')
65
+ ]
66
+ when 'helper'
67
+ [File.join(root_directory, HELPER_DIR, '%PLURALIZED_MODEL_NAME%_helper.rb')]
68
+ else
69
+ []
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def test_files(root_directory)
76
+ [
77
+ File.join(root_directory, UNIT_TEST_DIR, '%MODEL_NAME%_test.rb'),
78
+ File.join(root_directory, MODEL_TEST_DIR, '%MODEL_NAME%_test.rb'),
79
+ File.join(root_directory, SPEC_MODEL_DIR, '%MODEL_NAME%_spec.rb')
80
+ ]
81
+ end
82
+
83
+ def fixture_files(root_directory)
84
+ [
85
+ File.join(root_directory, FIXTURE_TEST_DIR, '%TABLE_NAME%.yml'),
86
+ File.join(root_directory, FIXTURE_SPEC_DIR, '%TABLE_NAME%.yml'),
87
+ File.join(root_directory, FIXTURE_TEST_DIR, '%PLURALIZED_MODEL_NAME%.yml'),
88
+ File.join(root_directory, FIXTURE_SPEC_DIR, '%PLURALIZED_MODEL_NAME%.yml')
89
+ ]
90
+ end
91
+
92
+ def scaffold_files(root_directory)
93
+ [
94
+ File.join(root_directory, CONTROLLER_TEST_DIR, '%PLURALIZED_MODEL_NAME%_controller_test.rb'),
95
+ File.join(root_directory, CONTROLLER_SPEC_DIR, '%PLURALIZED_MODEL_NAME%_controller_spec.rb'),
96
+ File.join(root_directory, REQUEST_SPEC_DIR, '%PLURALIZED_MODEL_NAME%_spec.rb'),
97
+ File.join(root_directory, ROUTING_SPEC_DIR, '%PLURALIZED_MODEL_NAME%_routing_spec.rb')
98
+ ]
99
+ end
100
+
101
+ def factory_files(root_directory)
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_BOT_TEST_DIR, '%MODEL_NAME%_factory.rb'), # (old style)
108
+ File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%MODEL_NAME%_factory.rb'), # (old style)
109
+ File.join(root_directory, FACTORY_BOT_TEST_DIR, '%TABLE_NAME%.rb'), # (new style)
110
+ File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%TABLE_NAME%.rb'), # (new style)
111
+ File.join(root_directory, FACTORY_BOT_TEST_DIR, '%PLURALIZED_MODEL_NAME%.rb'), # (new style)
112
+ File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%PLURALIZED_MODEL_NAME%.rb'), # (new style)
113
+ File.join(root_directory, FABRICATORS_TEST_DIR, '%MODEL_NAME%_fabricator.rb'),
114
+ File.join(root_directory, FABRICATORS_SPEC_DIR, '%MODEL_NAME%_fabricator.rb')
115
+ ]
116
+ end
117
+
118
+ def serialize_files(root_directory)
119
+ [
120
+ File.join(root_directory, SERIALIZERS_DIR, '%MODEL_NAME%_serializer.rb'),
121
+ File.join(root_directory, SERIALIZERS_TEST_DIR, '%MODEL_NAME%_serializer_test.rb'),
122
+ File.join(root_directory, SERIALIZERS_SPEC_DIR, '%MODEL_NAME%_serializer_spec.rb')
123
+ ]
124
+ end
125
+ end
126
+ end
127
+ end
@@ -3,6 +3,7 @@
3
3
  require 'bigdecimal'
4
4
 
5
5
  require 'annotate/constants'
6
+ require_relative 'annotate_models/file_patterns'
6
7
 
7
8
  module AnnotateModels
8
9
  # Annotate Models plugin use this header
@@ -16,50 +17,6 @@ module AnnotateModels
16
17
 
17
18
  MATCHED_TYPES = %w(test fixture factory serializer scaffold controller helper).freeze
18
19
 
19
- # File.join for windows reverse bar compat?
20
- # I dont use windows, can`t test
21
- UNIT_TEST_DIR = File.join('test', "unit")
22
- MODEL_TEST_DIR = File.join('test', "models") # since rails 4.0
23
- SPEC_MODEL_DIR = File.join('spec', "models")
24
- FIXTURE_TEST_DIR = File.join('test', "fixtures")
25
- FIXTURE_SPEC_DIR = File.join('spec', "fixtures")
26
-
27
- # Other test files
28
- CONTROLLER_TEST_DIR = File.join('test', "controllers")
29
- CONTROLLER_SPEC_DIR = File.join('spec', "controllers")
30
- REQUEST_SPEC_DIR = File.join('spec', "requests")
31
- ROUTING_SPEC_DIR = File.join('spec', "routing")
32
-
33
- # Object Daddy http://github.com/flogic/object_daddy/tree/master
34
- EXEMPLARS_TEST_DIR = File.join('test', "exemplars")
35
- EXEMPLARS_SPEC_DIR = File.join('spec', "exemplars")
36
-
37
- # Machinist http://github.com/notahat/machinist
38
- BLUEPRINTS_TEST_DIR = File.join('test', "blueprints")
39
- BLUEPRINTS_SPEC_DIR = File.join('spec', "blueprints")
40
-
41
- # Factory Bot https://github.com/thoughtbot/factory_bot
42
- FACTORY_BOT_TEST_DIR = File.join('test', "factories")
43
- FACTORY_BOT_SPEC_DIR = File.join('spec', "factories")
44
-
45
- # Fabrication https://github.com/paulelliott/fabrication.git
46
- FABRICATORS_TEST_DIR = File.join('test', "fabricators")
47
- FABRICATORS_SPEC_DIR = File.join('spec', "fabricators")
48
-
49
- # Serializers https://github.com/rails-api/active_model_serializers
50
- SERIALIZERS_DIR = File.join('app', "serializers")
51
- SERIALIZERS_TEST_DIR = File.join('test', "serializers")
52
- SERIALIZERS_SPEC_DIR = File.join('spec', "serializers")
53
-
54
- # Controller files
55
- CONTROLLER_DIR = File.join('app', "controllers")
56
-
57
- # Active admin registry files
58
- ACTIVEADMIN_DIR = File.join('app', "admin")
59
-
60
- # Helper files
61
- HELPER_DIR = File.join('app', "helpers")
62
-
63
20
  # Don't show limit (#) on these column types
64
21
  # Example: show "integer" instead of "integer(4)"
65
22
  NO_LIMIT_COL_TYPES = %w(integer bigint boolean).freeze
@@ -110,82 +67,24 @@ module AnnotateModels
110
67
 
111
68
  attr_writer :root_dir
112
69
 
113
- def test_files(root_directory)
114
- [
115
- File.join(root_directory, UNIT_TEST_DIR, "%MODEL_NAME%_test.rb"),
116
- File.join(root_directory, MODEL_TEST_DIR, "%MODEL_NAME%_test.rb"),
117
- File.join(root_directory, SPEC_MODEL_DIR, "%MODEL_NAME%_spec.rb")
118
- ]
119
- end
120
-
121
- def fixture_files(root_directory)
122
- [
123
- File.join(root_directory, FIXTURE_TEST_DIR, "%TABLE_NAME%.yml"),
124
- File.join(root_directory, FIXTURE_SPEC_DIR, "%TABLE_NAME%.yml"),
125
- File.join(root_directory, FIXTURE_TEST_DIR, "%PLURALIZED_MODEL_NAME%.yml"),
126
- File.join(root_directory, FIXTURE_SPEC_DIR, "%PLURALIZED_MODEL_NAME%.yml")
127
- ]
128
- end
129
-
130
- def scaffold_files(root_directory)
131
- [
132
- File.join(root_directory, CONTROLLER_TEST_DIR, "%PLURALIZED_MODEL_NAME%_controller_test.rb"),
133
- File.join(root_directory, CONTROLLER_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_controller_spec.rb"),
134
- File.join(root_directory, REQUEST_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_spec.rb"),
135
- File.join(root_directory, ROUTING_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_routing_spec.rb")
136
- ]
137
- end
138
-
139
- def factory_files(root_directory)
140
- [
141
- File.join(root_directory, EXEMPLARS_TEST_DIR, "%MODEL_NAME%_exemplar.rb"),
142
- File.join(root_directory, EXEMPLARS_SPEC_DIR, "%MODEL_NAME%_exemplar.rb"),
143
- File.join(root_directory, BLUEPRINTS_TEST_DIR, "%MODEL_NAME%_blueprint.rb"),
144
- File.join(root_directory, BLUEPRINTS_SPEC_DIR, "%MODEL_NAME%_blueprint.rb"),
145
- File.join(root_directory, FACTORY_BOT_TEST_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
146
- File.join(root_directory, FACTORY_BOT_SPEC_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
147
- File.join(root_directory, FACTORY_BOT_TEST_DIR, "%TABLE_NAME%.rb"), # (new style)
148
- File.join(root_directory, FACTORY_BOT_SPEC_DIR, "%TABLE_NAME%.rb"), # (new style)
149
- File.join(root_directory, FACTORY_BOT_TEST_DIR, "%PLURALIZED_MODEL_NAME%.rb"), # (new style)
150
- File.join(root_directory, FACTORY_BOT_SPEC_DIR, "%PLURALIZED_MODEL_NAME%.rb"), # (new style)
151
- File.join(root_directory, FABRICATORS_TEST_DIR, "%MODEL_NAME%_fabricator.rb"),
152
- File.join(root_directory, FABRICATORS_SPEC_DIR, "%MODEL_NAME%_fabricator.rb")
153
- ]
154
- end
155
-
156
- def serialize_files(root_directory)
157
- [
158
- File.join(root_directory, SERIALIZERS_DIR, "%MODEL_NAME%_serializer.rb"),
159
- File.join(root_directory, SERIALIZERS_TEST_DIR, "%MODEL_NAME%_serializer_test.rb"),
160
- File.join(root_directory, SERIALIZERS_SPEC_DIR, "%MODEL_NAME%_serializer_spec.rb")
161
- ]
162
- end
70
+ def skip_subdirectory_model_load
71
+ # This option is set in options[:skip_subdirectory_model_load]
72
+ # and stops the get_loaded_model method from loading a model from a subdir
163
73
 
164
- def files_by_pattern(root_directory, pattern_type, options)
165
- case pattern_type
166
- when 'test' then test_files(root_directory)
167
- when 'fixture' then fixture_files(root_directory)
168
- when 'scaffold' then scaffold_files(root_directory)
169
- when 'factory' then factory_files(root_directory)
170
- when 'serializer' then serialize_files(root_directory)
171
- when 'additional_file_patterns'
172
- [options[:additional_file_patterns] || []].flatten
173
- when 'controller'
174
- [File.join(root_directory, CONTROLLER_DIR, "%PLURALIZED_MODEL_NAME%_controller.rb")]
175
- when 'admin'
176
- [File.join(root_directory, ACTIVEADMIN_DIR, "%MODEL_NAME%.rb")]
177
- when 'helper'
178
- [File.join(root_directory, HELPER_DIR, "%PLURALIZED_MODEL_NAME%_helper.rb")]
74
+ if @skip_subdirectory_model_load.blank?
75
+ false
179
76
  else
180
- []
77
+ @skip_subdirectory_model_load
181
78
  end
182
79
  end
183
80
 
81
+ attr_writer :skip_subdirectory_model_load
82
+
184
83
  def get_patterns(options, pattern_types = [])
185
84
  current_patterns = []
186
85
  root_dir.each do |root_directory|
187
86
  Array(pattern_types).each do |pattern_type|
188
- patterns = files_by_pattern(root_directory, pattern_type, options)
87
+ patterns = FilePatterns.generate(root_directory, pattern_type, options)
189
88
 
190
89
  current_patterns += if pattern_type.to_sym == :additional_file_patterns
191
90
  patterns
@@ -249,52 +148,13 @@ module AnnotateModels
249
148
  cols = columns(klass, options)
250
149
  cols.each do |col|
251
150
  col_type = get_col_type(col)
252
- attrs = []
253
- attrs << "default(#{schema_default(klass, col)})" unless col.default.nil? || hide_default?(col_type, options)
254
- attrs << 'unsigned' if col.respond_to?(:unsigned?) && col.unsigned?
255
- attrs << 'not null' unless col.null
256
- attrs << 'primary key' if klass.primary_key && (klass.primary_key.is_a?(Array) ? klass.primary_key.collect(&:to_sym).include?(col.name.to_sym) : col.name.to_sym == klass.primary_key.to_sym)
257
-
258
- if col_type == 'decimal'
259
- col_type << "(#{col.precision}, #{col.scale})"
260
- elsif !%w[spatial geometry geography].include?(col_type)
261
- if col.limit && !options[:format_yard]
262
- if col.limit.is_a? Array
263
- attrs << "(#{col.limit.join(', ')})"
264
- else
265
- col_type << "(#{col.limit})" unless hide_limit?(col_type, options)
266
- end
267
- end
268
- end
269
-
270
- # Check out if we got an array column
271
- attrs << 'is an Array' if col.respond_to?(:array) && col.array
272
-
273
- # Check out if we got a geometric column
274
- # and print the type and SRID
275
- if col.respond_to?(:geometry_type)
276
- attrs << "#{col.geometry_type}, #{col.srid}"
277
- elsif col.respond_to?(:geometric_type) && col.geometric_type.present?
278
- attrs << "#{col.geometric_type.to_s.downcase}, #{col.srid}"
279
- end
280
-
281
- # Check if the column has indices and print "indexed" if true
282
- # If the index includes another column, print it too.
283
- if options[:simple_indexes] && klass.table_exists?# Check out if this column is indexed
284
- indices = retrieve_indexes_from_table(klass)
285
- if indices = indices.select { |ind| ind.columns.include? col.name }
286
- indices.sort_by(&:name).each do |ind|
287
- next if ind.columns.is_a?(String)
288
- ind = ind.columns.reject! { |i| i == col.name }
289
- attrs << (ind.empty? ? "indexed" : "indexed => [#{ind.join(", ")}]")
290
- end
291
- end
292
- end
151
+ attrs = get_attributes(col, col_type, klass, options)
293
152
  col_name = if with_comments?(klass, options) && col.comment
294
- "#{col.name}(#{col.comment})"
153
+ "#{col.name}(#{col.comment.gsub(/\n/, "\\n")})"
295
154
  else
296
155
  col.name
297
156
  end
157
+
298
158
  if options[:format_rdoc]
299
159
  info << sprintf("# %-#{max_size}.#{max_size}s<tt>%s</tt>", "*#{col_name}*::", attrs.unshift(col_type).join(", ")).rstrip + "\n"
300
160
  elsif options[:format_yard]
@@ -739,14 +599,17 @@ module AnnotateModels
739
599
 
740
600
  # Retrieve loaded model class
741
601
  def get_loaded_model(model_path, file)
742
- loaded_model_class = get_loaded_model_by_path(model_path)
743
- return loaded_model_class if loaded_model_class
602
+ unless skip_subdirectory_model_load
603
+ loaded_model_class = get_loaded_model_by_path(model_path)
604
+ return loaded_model_class if loaded_model_class
605
+ end
744
606
 
745
607
  # We cannot get loaded model when `model_path` is loaded by Rails
746
608
  # auto_load/eager_load paths. Try all possible model paths one by one.
747
609
  absolute_file = File.expand_path(file)
748
610
  model_paths =
749
- $LOAD_PATH.select { |path| absolute_file.include?(path) }
611
+ $LOAD_PATH.map(&:to_s)
612
+ .select { |path| absolute_file.include?(path) }
750
613
  .map { |path| absolute_file.sub(path, '').sub(/\.rb$/, '').sub(/^\//, '') }
751
614
  model_paths
752
615
  .map { |path| get_loaded_model_by_path(path) }
@@ -769,6 +632,7 @@ module AnnotateModels
769
632
  def parse_options(options = {})
770
633
  self.model_dir = split_model_dir(options[:model_dir]) if options[:model_dir]
771
634
  self.root_dir = options[:root_dir] if options[:root_dir]
635
+ self.skip_subdirectory_model_load = options[:skip_subdirectory_model_load].present?
772
636
  end
773
637
 
774
638
  def split_model_dir(option_value)
@@ -809,7 +673,7 @@ module AnnotateModels
809
673
  begin
810
674
  return false if /#{SKIP_ANNOTATION_PREFIX}.*/ =~ (File.exist?(file) ? File.read(file) : '')
811
675
  klass = get_model_class(file)
812
- do_annotate = klass &&
676
+ do_annotate = klass.is_a?(Class) &&
813
677
  klass < ActiveRecord::Base &&
814
678
  (!options[:exclude_sti_subclasses] || !(klass.superclass < ActiveRecord::Base && klass.table_name == klass.superclass.table_name)) &&
815
679
  !klass.abstract_class? &&
@@ -982,9 +846,7 @@ module AnnotateModels
982
846
  # Construct the foreign column name in the translations table
983
847
  # eg. Model: Car, foreign column name: car_id
984
848
  foreign_column_name = [
985
- klass.translation_class.to_s
986
- .gsub('::Translation', '').gsub('::', '_')
987
- .downcase,
849
+ klass.table_name.to_s.singularize,
988
850
  '_id'
989
851
  ].join.to_sym
990
852
 
@@ -996,6 +858,55 @@ module AnnotateModels
996
858
  foreign_column_name
997
859
  ]
998
860
  end
861
+
862
+ ##
863
+ # Get the list of attributes that should be included in the annotation for
864
+ # a given column.
865
+ def get_attributes(column, column_type, klass, options)
866
+ attrs = []
867
+ attrs << "default(#{schema_default(klass, column)})" unless column.default.nil? || hide_default?(column_type, options)
868
+ attrs << 'unsigned' if column.respond_to?(:unsigned?) && column.unsigned?
869
+ attrs << 'not null' unless column.null
870
+ attrs << 'primary key' if klass.primary_key && (klass.primary_key.is_a?(Array) ? klass.primary_key.collect(&:to_sym).include?(column.name.to_sym) : column.name.to_sym == klass.primary_key.to_sym)
871
+
872
+ if column_type == 'decimal'
873
+ column_type << "(#{column.precision}, #{column.scale})"
874
+ elsif !%w[spatial geometry geography].include?(column_type)
875
+ if column.limit && !options[:format_yard]
876
+ if column.limit.is_a? Array
877
+ attrs << "(#{column.limit.join(', ')})"
878
+ else
879
+ column_type << "(#{column.limit})" unless hide_limit?(column_type, options)
880
+ end
881
+ end
882
+ end
883
+
884
+ # Check out if we got an array column
885
+ attrs << 'is an Array' if column.respond_to?(:array) && column.array
886
+
887
+ # Check out if we got a geometric column
888
+ # and print the type and SRID
889
+ if column.respond_to?(:geometry_type)
890
+ attrs << [column.geometry_type, column.try(:srid)].compact.join(', ')
891
+ elsif column.respond_to?(:geometric_type) && column.geometric_type.present?
892
+ attrs << [column.geometric_type.to_s.downcase, column.try(:srid)].compact.join(', ')
893
+ end
894
+
895
+ # Check if the column has indices and print "indexed" if true
896
+ # If the index includes another column, print it too.
897
+ if options[:simple_indexes] && klass.table_exists?# Check out if this column is indexed
898
+ indices = retrieve_indexes_from_table(klass)
899
+ if indices = indices.select { |ind| ind.columns.include? column.name }
900
+ indices.sort_by(&:name).each do |ind|
901
+ next if ind.columns.is_a?(String)
902
+ ind = ind.columns.reject! { |i| i == column.name }
903
+ attrs << (ind.empty? ? "indexed" : "indexed => [#{ind.join(", ")}]")
904
+ end
905
+ end
906
+ end
907
+
908
+ attrs
909
+ end
999
910
  end
1000
911
 
1001
912
  class BadModelFileError < LoadError
@@ -0,0 +1,113 @@
1
+ require_relative './helpers'
2
+
3
+ module AnnotateRoutes
4
+ class HeaderGenerator
5
+ PREFIX = '== Route Map'.freeze
6
+ PREFIX_MD = '## Route Map'.freeze
7
+ HEADER_ROW = ['Prefix', 'Verb', 'URI Pattern', 'Controller#Action'].freeze
8
+
9
+ class << self
10
+ def generate(options = {})
11
+ new(options, routes_map(options)).generate
12
+ end
13
+
14
+ private :new
15
+
16
+ private
17
+
18
+ def routes_map(options)
19
+ result = `rake routes`.chomp("\n").split(/\n/, -1)
20
+
21
+ # In old versions of Rake, the first line of output was the cwd. Not so
22
+ # much in newer ones. We ditch that line if it exists, and if not, we
23
+ # keep the line around.
24
+ result.shift if result.first =~ %r{^\(in \/}
25
+
26
+ ignore_routes = options[:ignore_routes]
27
+ regexp_for_ignoring_routes = ignore_routes ? /#{ignore_routes}/ : nil
28
+
29
+ # Skip routes which match given regex
30
+ # Note: it matches the complete line (route_name, path, controller/action)
31
+ if regexp_for_ignoring_routes
32
+ result.reject { |line| line =~ regexp_for_ignoring_routes }
33
+ else
34
+ result
35
+ end
36
+ end
37
+ end
38
+
39
+ def initialize(options, routes_map)
40
+ @options = options
41
+ @routes_map = routes_map
42
+ end
43
+
44
+ def generate
45
+ magic_comments_map, contents_without_magic_comments = Helpers.extract_magic_comments_from_array(routes_map)
46
+
47
+ out = []
48
+
49
+ magic_comments_map.each do |magic_comment|
50
+ out << magic_comment
51
+ end
52
+ out << '' if magic_comments_map.any?
53
+
54
+ out << comment(options[:wrapper_open]) if options[:wrapper_open]
55
+
56
+ out << comment(markdown? ? PREFIX_MD : PREFIX) + timestamp_if_required
57
+ out << comment
58
+ return out if contents_without_magic_comments.size.zero?
59
+
60
+ maxs = [HEADER_ROW.map(&:size)] + contents_without_magic_comments[1..-1].map { |line| line.split.map(&:size) }
61
+
62
+ if markdown?
63
+ max = maxs.map(&:max).compact.max
64
+
65
+ out << comment(content(HEADER_ROW, maxs))
66
+ out << comment(content(['-' * max, '-' * max, '-' * max, '-' * max], maxs))
67
+ else
68
+ out << comment(content(contents_without_magic_comments[0], maxs))
69
+ end
70
+
71
+ out += contents_without_magic_comments[1..-1].map { |line| comment(content(markdown? ? line.split(' ') : line, maxs)) }
72
+ out << comment(options[:wrapper_close]) if options[:wrapper_close]
73
+
74
+ out
75
+ end
76
+
77
+ private
78
+
79
+ attr_reader :options, :routes_map
80
+
81
+ def comment(row = '')
82
+ if row == ''
83
+ '#'
84
+ else
85
+ "# #{row}"
86
+ end
87
+ end
88
+
89
+ def content(line, maxs)
90
+ return line.rstrip unless markdown?
91
+
92
+ line.each_with_index.map { |elem, index| format_line_element(elem, maxs, index) }.join(' | ')
93
+ end
94
+
95
+ def format_line_element(elem, maxs, index)
96
+ min_length = maxs.map { |arr| arr[index] }.max || 0
97
+ format("%-#{min_length}.#{min_length}s", elem.tr('|', '-'))
98
+ end
99
+
100
+ def markdown?
101
+ options[:format_markdown]
102
+ end
103
+
104
+ def timestamp_if_required(time = Time.now)
105
+ if options[:timestamp]
106
+ time_formatted = time.strftime('%Y-%m-%d %H:%M')
107
+ " (Updated #{time_formatted})"
108
+ else
109
+ ''
110
+ end
111
+ end
112
+ end
113
+ end
@@ -1,5 +1,3 @@
1
- # rubocop:disable Metrics/ModuleLength
2
-
3
1
  # == Annotate Routes
4
2
  #
5
3
  # Based on:
@@ -21,18 +19,15 @@
21
19
  #
22
20
 
23
21
  require_relative './annotate_routes/helpers'
22
+ require_relative './annotate_routes/header_generator'
24
23
 
25
24
  module AnnotateRoutes
26
- PREFIX = '== Route Map'.freeze
27
- PREFIX_MD = '## Route Map'.freeze
28
- HEADER_ROW = ['Prefix', 'Verb', 'URI Pattern', 'Controller#Action'].freeze
29
-
30
25
  class << self
31
26
  def do_annotations(options = {})
32
27
  if routes_file_exist?
33
28
  existing_text = File.read(routes_file)
34
29
  content, header_position = Helpers.strip_annotations(existing_text)
35
- new_content = annotate_routes(header(options), content, header_position, options)
30
+ new_content = annotate_routes(HeaderGenerator.generate(options), content, header_position, options)
36
31
  new_text = new_content.join("\n")
37
32
 
38
33
  if rewrite_contents(existing_text, new_text)
@@ -71,49 +66,6 @@ module AnnotateRoutes
71
66
  @routes_rb ||= File.join('config', 'routes.rb')
72
67
  end
73
68
 
74
- def header(options = {})
75
- routes_map = app_routes_map(options)
76
-
77
- magic_comments_map, routes_map = Helpers.extract_magic_comments_from_array(routes_map)
78
-
79
- out = []
80
-
81
- magic_comments_map.each do |magic_comment|
82
- out << magic_comment
83
- end
84
- out << '' if magic_comments_map.any?
85
-
86
- out << comment(options[:wrapper_open]) if options[:wrapper_open]
87
-
88
- out << comment(options[:format_markdown] ? PREFIX_MD : PREFIX) + (options[:timestamp] ? " (Updated #{Time.now.strftime('%Y-%m-%d %H:%M')})" : '')
89
- out << comment
90
- return out if routes_map.size.zero?
91
-
92
- maxs = [HEADER_ROW.map(&:size)] + routes_map[1..-1].map { |line| line.split.map(&:size) }
93
-
94
- if options[:format_markdown]
95
- max = maxs.map(&:max).compact.max
96
-
97
- out << comment(content(HEADER_ROW, maxs, options))
98
- out << comment(content(['-' * max, '-' * max, '-' * max, '-' * max], maxs, options))
99
- else
100
- out << comment(content(routes_map[0], maxs, options))
101
- end
102
-
103
- out += routes_map[1..-1].map { |line| comment(content(options[:format_markdown] ? line.split(' ') : line, maxs, options)) }
104
- out << comment(options[:wrapper_close]) if options[:wrapper_close]
105
-
106
- out
107
- end
108
-
109
- def comment(row = '')
110
- if row == ''
111
- '#'
112
- else
113
- "# #{row}"
114
- end
115
- end
116
-
117
69
  def strip_on_removal(content, header_position)
118
70
  if header_position == :before
119
71
  content.shift while content.first == ''
@@ -162,32 +114,5 @@ module AnnotateRoutes
162
114
 
163
115
  new_content
164
116
  end
165
-
166
- def app_routes_map(options)
167
- routes_map = `rake routes`.chomp("\n").split(/\n/, -1)
168
-
169
- # In old versions of Rake, the first line of output was the cwd. Not so
170
- # much in newer ones. We ditch that line if it exists, and if not, we
171
- # keep the line around.
172
- routes_map.shift if routes_map.first =~ /^\(in \//
173
-
174
- # Skip routes which match given regex
175
- # Note: it matches the complete line (route_name, path, controller/action)
176
- if options[:ignore_routes]
177
- routes_map.reject! { |line| line =~ /#{options[:ignore_routes]}/ }
178
- end
179
-
180
- routes_map
181
- end
182
-
183
- def content(line, maxs, options = {})
184
- return line.rstrip unless options[:format_markdown]
185
-
186
- line.each_with_index.map do |elem, index|
187
- min_length = maxs.map { |arr| arr[index] }.max || 0
188
-
189
- sprintf("%-#{min_length}.#{min_length}s", elem.tr('|', '-'))
190
- end.join(' | ')
191
- end
192
117
  end
193
118
  end
@@ -1,5 +1,5 @@
1
1
  module Annotate
2
2
  def self.version
3
- '3.1.1'
3
+ '3.2.0'
4
4
  end
5
5
  end
@@ -4,7 +4,20 @@
4
4
  # Append annotations to Rake tasks for ActiveRecord, so annotate automatically gets
5
5
  # run after doing db:migrate.
6
6
 
7
- %w(db:migrate db:migrate:up db:migrate:down db:migrate:reset db:migrate:redo db:rollback).each do |task|
7
+ migration_tasks = %w(db:migrate db:migrate:up db:migrate:down db:migrate:reset db:migrate:redo db:rollback)
8
+ if defined?(Rails::Application) && Rails.version.split('.').first.to_i >= 6
9
+ require 'active_record'
10
+
11
+ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
12
+
13
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
14
+ migration_tasks.concat(%w(db:migrate db:migrate:up db:migrate:down).map { |task| "#{task}:#{spec_name}" })
15
+ end
16
+ end
17
+
18
+ migration_tasks.each do |task|
19
+ next unless Rake::Task.task_defined?(task)
20
+
8
21
  Rake::Task[task].enhance do
9
22
  Rake::Task[Rake.application.top_level_tasks.last].enhance do
10
23
  annotation_options_task = if Rake::Task.task_defined?('app:set_annotation_options')
@@ -1,6 +1,12 @@
1
+ annotate_lib = File.expand_path(File.dirname(File.dirname(__FILE__)))
2
+
3
+ unless ENV['is_cli']
4
+ task :set_annotation_options
5
+ task annotate_routes: :set_annotation_options
6
+ end
7
+
1
8
  desc "Adds the route map to routes.rb"
2
9
  task :annotate_routes => :environment do
3
- annotate_lib = File.expand_path(File.dirname(File.dirname(__FILE__)))
4
10
  require "#{annotate_lib}/annotate/annotate_routes"
5
11
 
6
12
  options={}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: annotate
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Chaffee
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2020-03-24 00:00:00.000000000 Z
15
+ date: 2022-02-10 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rake
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '3.2'
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
- version: '7.0'
46
+ version: '8.0'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
@@ -53,7 +53,7 @@ dependencies:
53
53
  version: '3.2'
54
54
  - - "<"
55
55
  - !ruby/object:Gem::Version
56
- version: '7.0'
56
+ version: '8.0'
57
57
  description: Annotates Rails/ActiveRecord Models, routes, fixtures, and others based
58
58
  on the database schema.
59
59
  email:
@@ -79,7 +79,9 @@ files:
79
79
  - lib/annotate.rb
80
80
  - lib/annotate/active_record_patch.rb
81
81
  - lib/annotate/annotate_models.rb
82
+ - lib/annotate/annotate_models/file_patterns.rb
82
83
  - lib/annotate/annotate_routes.rb
84
+ - lib/annotate/annotate_routes/header_generator.rb
83
85
  - lib/annotate/annotate_routes/helpers.rb
84
86
  - lib/annotate/constants.rb
85
87
  - lib/annotate/helpers.rb
@@ -93,11 +95,12 @@ files:
93
95
  - lib/tasks/annotate_models_migrate.rake
94
96
  - lib/tasks/annotate_routes.rake
95
97
  - potato.md
96
- homepage: http://github.com/ctran/annotate_models
98
+ homepage: https://github.com/ctran/annotate_models
97
99
  licenses:
98
100
  - Ruby
99
101
  metadata:
100
- github_repo: ssh://github.com/ctran/annotate_models
102
+ bug_tracker_uri: https://github.com/ctran/annotate_models/issues/
103
+ source_code_uri: https://github.com/ctran/annotate_models.git
101
104
  post_install_message:
102
105
  rdoc_options: []
103
106
  require_paths:
@@ -113,8 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
116
  - !ruby/object:Gem::Version
114
117
  version: '0'
115
118
  requirements: []
116
- rubyforge_project:
117
- rubygems_version: 2.7.7
119
+ rubygems_version: 3.3.7
118
120
  signing_key:
119
121
  specification_version: 4
120
122
  summary: Annotates Rails Models, routes, fixtures, and others based on the database