annotaterb 4.17.0 → 4.18.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: 8789a11055d7fe2e2631a4c8ca0b3e05e20e365c16a31a2ea21ba6c1f90eda60
4
- data.tar.gz: cbd50d2e0be48c2ffc55c600b5e1a5d6ae5864224d04180924a473395c1543eb
3
+ metadata.gz: 0276a5044aa1b444f73aac5612004ce9a8c05c6d47634fb2e8798c24a442fed5
4
+ data.tar.gz: 58cd27cb187989b06c459979ac0152db9dfdb54d671b9348980c244caa7981a6
5
5
  SHA512:
6
- metadata.gz: a51864d58bb429fd7166c16c98e179c926b5d2cf06b294f7b476f36e6dce5662d5f3ea20881ef0ac773535f3ccd3ddf4e26d35d833ba813bbc955a38191a2ea5
7
- data.tar.gz: 78349c0ac08e212a9c6c0d40315d4bb18eba61e0dea77a580c133b76235a04cd3e78072c6d85814d3081de3e7c53eaa19e7297f9148e3c45bfe8567cbe7ce559
6
+ metadata.gz: ac0f491e7022299fc96029950c5edf2b0e05aa38e9f3198ec37acbd04275888be493f4202f31295e8db0ad7737cc03d2c6b52e5fbb51c24418ef92f40da77a13
7
+ data.tar.gz: 914216a38c137682acb6e2b58154c3af47dba3b0ebb424b69194a59c3939cfdd01c00d0f75a10bb51800f2ea6ce3f4dc97f3cdcd592ff7f77e7cafc906cd660f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## [v4.17.0](https://github.com/drwl/annotaterb/tree/v4.17.0) (2025-07-14)
4
+
5
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.16.0...v4.17.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Place column comments at the end of the line \(feature suggestion\) [\#164](https://github.com/drwl/annotaterb/issues/164)
10
+
11
+ **Fixed bugs:**
12
+
13
+ - Model annotation chokes on an empty file [\#182](https://github.com/drwl/annotaterb/issues/182)
14
+
15
+ **Closed issues:**
16
+
17
+ - uninitialized constant Zeitwerk::VERSION [\#216](https://github.com/drwl/annotaterb/issues/216)
18
+ - Incorrect annotation of fixture files when different models share the same table name in different databases [\#206](https://github.com/drwl/annotaterb/issues/206)
19
+ - Should active record and active support be in the gemspec? [\#197](https://github.com/drwl/annotaterb/issues/197)
20
+
21
+ **Merged pull requests:**
22
+
23
+ - Bump version to v4.17.0 [\#234](https://github.com/drwl/annotaterb/pull/234) ([drwl](https://github.com/drwl))
24
+ - Fix NoMethodError when processing empty files [\#232](https://github.com/drwl/annotaterb/pull/232) ([tanukiti1987](https://github.com/tanukiti1987))
25
+ - Refactor column ignore to use `match?` [\#231](https://github.com/drwl/annotaterb/pull/231) ([tagliala](https://github.com/tagliala))
26
+ - Fix standard configuration [\#230](https://github.com/drwl/annotaterb/pull/230) ([tagliala](https://github.com/tagliala))
27
+ - Generate changelog for v4.16.0 [\#229](https://github.com/drwl/annotaterb/pull/229) ([drwl](https://github.com/drwl))
28
+ - show included columns in indexes [\#211](https://github.com/drwl/annotaterb/pull/211) ([pineman](https://github.com/pineman))
29
+ - fix: use model name for file retrieval when not connected to the primary DB. [\#207](https://github.com/drwl/annotaterb/pull/207) ([OdenTakashi](https://github.com/OdenTakashi))
30
+ - Place column comments at the end of the line [\#199](https://github.com/drwl/annotaterb/pull/199) ([Adeynack](https://github.com/Adeynack))
31
+
3
32
  ## [v4.16.0](https://github.com/drwl/annotaterb/tree/v4.16.0) (2025-06-18)
4
33
 
5
34
  [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.15.0...v4.16.0)
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  ## AnnotateRb
2
+
2
3
  ### forked from the [Annotate aka AnnotateModels gem](https://github.com/ctran/annotate_models)
3
4
 
4
5
  A Ruby Gem that adds annotations to your Rails models and route files.
5
6
 
6
- ----------
7
+ ---
8
+
7
9
  [![CI](https://github.com/drwl/annotaterb/actions/workflows/ci.yml/badge.svg)](https://github.com/drwl/annotaterb/actions/workflows/ci.yml)
8
10
  [![Gem Version](https://badge.fury.io/rb/annotaterb.svg)](https://badge.fury.io/rb/annotaterb)
9
11
 
@@ -32,7 +34,9 @@ The schema comment looks like this:
32
34
  class Task < ApplicationRecord
33
35
  ...
34
36
  ```
35
- ----------
37
+
38
+ ---
39
+
36
40
  ## Installation
37
41
 
38
42
  ```sh
@@ -46,11 +50,12 @@ group :development do
46
50
  ...
47
51
 
48
52
  gem "annotaterb"
49
-
53
+
50
54
  ...
51
55
  ```
52
56
 
53
57
  ### Automatically annotate models
58
+
54
59
  For Rails projects, model files can get automatically annotated after migration tasks. To do this, run the following command:
55
60
 
56
61
  ```sh
@@ -66,6 +71,7 @@ $ ANNOTATERB_SKIP_ON_DB_TASKS=1 bin/rails db:migrate
66
71
  ```
67
72
 
68
73
  ### Added Rails generators
74
+
69
75
  The following Rails generator commands get added.
70
76
 
71
77
  ```sh
@@ -83,18 +89,23 @@ AnnotateRb:
83
89
  ```
84
90
 
85
91
  `bin/rails g annotate_rb:config`
92
+
86
93
  - Generates a new configuration file, `.annotaterb.yml`, using defaults from the gem.
87
94
 
88
95
  `bin/rails g annotate_rb:hook`
96
+
89
97
  - Installs the Rake file to automatically annotate Rails models on a database task (e.g. AnnotateRb will automatically run after running `bin/rails db:migrate`).
90
98
 
91
99
  `bin/rails g annotate_rb:install`
100
+
92
101
  - Runs the `config` and `hook` generator commands
93
102
 
94
103
  `bin/rails g annotate_rb:update_config`
104
+
95
105
  - Appends to `.annotaterb.yml` any configuration key-value pairs that are used by the Gem. This is useful when there's a drift between the config file values and the gem defaults (i.e. when new features get added).
96
106
 
97
107
  ## Migrating from the annotate gem
108
+
98
109
  Refer to the [migration guide](MIGRATION_GUIDE.md).
99
110
 
100
111
  ## Usage
@@ -103,7 +114,7 @@ AnnotateRb has a CLI that you can use to add or remove annotations.
103
114
 
104
115
  ```sh
105
116
  # To show the CLI options
106
- $ bundle exec annotaterb
117
+ $ bundle exec annotaterb
107
118
 
108
119
  Usage: annotaterb [command] [options]
109
120
 
@@ -127,6 +138,7 @@ Annotate model options:
127
138
  Complete foreign key names in the annotation
128
139
  -i, --show-indexes List the table's database indexes in the annotation
129
140
  -s, --simple-indexes Concat the column's related indexes in the annotation
141
+ -c, --show-check-constraints List the table's check constraints in the annotation
130
142
  --hide-limit-column-types VALUES
131
143
  don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)
132
144
  --hide-default-column-types VALUES
@@ -134,7 +146,15 @@ Annotate model options:
134
146
  --ignore-unknown-models don't display warnings for bad model files
135
147
  -I, --ignore-columns REGEX don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`
136
148
  --with-comment include database comments in model annotations
137
- --with-column-comments include column comments in model annotations
149
+ --without-comment include database comments in model annotations
150
+ --with-column-comments include column comments in model annotations
151
+ --without-column-comments exclude column comments in model annotations
152
+ --position-of-column-comments VALUE
153
+ set the position, in the annotation block, of the column comment
154
+ --with-table-comments include table comments in model annotations
155
+ --without-table-comments exclude table comments in model annotations
156
+ --classes-default-to-s class Custom classes to be represented with `to_s`, may be used multiple times
157
+ --nested-position Place annotations directly above nested classes or modules instead of at the top of the file.
138
158
 
139
159
  Annotate routes options:
140
160
  Usage: annotaterb routes [options]
@@ -157,6 +177,7 @@ Additional options that work for annotating models and routes
157
177
  --ignore-model-subdirects Ignore subdirectories of the models directory
158
178
  --sort Sort columns alphabetically, rather than in creation order
159
179
  --classified-sort Sort columns alphabetically, but first goes id, then the rest columns, then the timestamp columns and then the association columns
180
+ --grouped-polymorphic Group polymorphic associations together in the annotation when using --classified-sort
160
181
  -R, --require path Additional file to require before loading models, may be used multiple times
161
182
  -e [tests,fixtures,factories,serializers],
162
183
  --exclude Do not annotate fixtures, test files, factories, and/or serializers
@@ -176,6 +197,8 @@ Additional options that work for annotating models and routes
176
197
  Place the annotations at the top (before) or the bottom (after) of the routes.rb file
177
198
  --ps, --position-in-serializer [before|top|after|bottom]
178
199
  Place the annotations at the top (before) or the bottom (after) of the serializer files
200
+ --pa, --position-in-additional-file-patterns [before|top|after|bottom]
201
+ Place the annotations at the top (before) or the bottom (after) of files captured in additional file patterns
179
202
  --force Force new annotations even if there are no changes.
180
203
  --debug Prints the options and outputs messages to make it easier to debug.
181
204
  --frozen Do not allow to change annotations. Exits non-zero if there are going to be changes to files.
@@ -185,6 +208,7 @@ Additional options that work for annotating models and routes
185
208
  ## Configuration
186
209
 
187
210
  ### Storing default options
211
+
188
212
  Previously in the [Annotate](https://github.com/ctran/annotate_models) you could pass options through the CLI or store them as environment variables. Annotaterb removes dependency on the environment variables and instead can read values from a `.annotaterb.yml` file stored in the Rails project root.
189
213
 
190
214
  ```yml
@@ -198,6 +222,7 @@ Annotaterb reads first the configuration file, if it exists, passes its content
198
222
  For further details visit the [section in the migration guide](MIGRATION_GUIDE.md#automatic-annotations-after-running-database-migration-commands).
199
223
 
200
224
  ### How to skip annotating a particular model
225
+
201
226
  If you want to always skip annotations on a particular model, add this string
202
227
  anywhere in the file:
203
228
 
@@ -211,6 +236,10 @@ migrations were run).
211
236
  If you prefer to sort alphabetically so that the results of annotation are
212
237
  consistent regardless of what order migrations are executed in, use `--sort`.
213
238
 
239
+ You can also sort columns by type, then alphabetically using `--classified-sort`
240
+ and `--grouped-polymorphic`: first goes id, then the rest columns, then the
241
+ timestamp columns and then the association columns.
242
+
214
243
  ## License
215
244
 
216
245
  Released under the same license as Ruby. No Support. No Warranty.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.17.0
1
+ 4.18.0
@@ -59,17 +59,7 @@ module AnnotateRb
59
59
  end
60
60
 
61
61
  def build
62
- if @options.get_state(:current_version).nil?
63
- migration_version = begin
64
- ActiveRecord::Migrator.current_version
65
- rescue
66
- 0
67
- end
68
-
69
- @options.set_state(:current_version, migration_version)
70
- end
71
-
72
- version = @options.get_state(:current_version)
62
+ version = migration_version_for_model(@model)
73
63
  table_name = @model.table_name
74
64
  table_comment = @model.connection.try(:table_comment, @model.table_name)
75
65
  max_size = @model.max_schema_info_width
@@ -78,6 +68,30 @@ module AnnotateRb
78
68
  version: version, table_name: table_name, table_comment: table_comment,
79
69
  max_size: max_size, model: @model).build
80
70
  end
71
+
72
+ private
73
+
74
+ def migration_version_for_model(model)
75
+ return 0 unless @options[:include_version]
76
+
77
+ # Multi-database support: Cache migration versions per database connection to handle
78
+ # different schema versions across primary/secondary databases correctly.
79
+ # Example: primary → "current_version_primary", secondary → "current_version_secondary"
80
+ connection_pool_name = model.connection.pool.db_config.name
81
+ cache_key = "current_version_#{connection_pool_name}".to_sym
82
+
83
+ if @options.get_state(cache_key).nil?
84
+ migration_version = begin
85
+ model.connection.migration_context.current_version
86
+ rescue
87
+ 0
88
+ end
89
+
90
+ @options.set_state(cache_key, migration_version)
91
+ end
92
+
93
+ @options.get_state(cache_key)
94
+ end
81
95
  end
82
96
  end
83
97
  end
@@ -16,29 +16,9 @@ module AnnotateRb
16
16
 
17
17
  begin
18
18
  klass = ModelClassGetter.call(@file, @options)
19
+ return false unless klass.respond_to?(:descends_from_active_record?) && klass.descends_from_active_record? && klass.table_exists?
19
20
 
20
- klass_is_a_class = klass.is_a?(Class)
21
- # Methods such as #superclass only exist on a class. Because of how the code is structured, `klass` could be a
22
- # module that does not support the #superclass method, so we want to return early.
23
- return false if !klass_is_a_class
24
-
25
- klass_inherits_active_record_base = klass < ActiveRecord::Base
26
- klass_is_not_abstract = klass.respond_to?(:abstract_class?) && !klass.abstract_class?
27
- klass_table_exists = klass.respond_to?(:table_exists?) && klass.table_exists?
28
-
29
- not_sure_this_conditional = (!@options[:exclude_sti_subclasses] || !(klass.superclass < ActiveRecord::Base && klass.table_name == klass.superclass.table_name))
30
-
31
- annotate_conditions = [
32
- klass_is_a_class,
33
- klass_inherits_active_record_base,
34
- not_sure_this_conditional,
35
- klass_is_not_abstract,
36
- klass_table_exists
37
- ]
38
-
39
- to_annotate = annotate_conditions.all?
40
-
41
- return to_annotate
21
+ return @options[:exclude_sti_subclasses] ? klass.base_class? : true
42
22
  rescue BadModelFileError => e
43
23
  unless @options[:ignore_unknown_models]
44
24
  warn "Unable to process #{@file}: #{e.message}"
@@ -55,9 +35,9 @@ module AnnotateRb
55
35
  private
56
36
 
57
37
  def file_contains_skip_annotation
58
- file_string = File.exist?(@file) ? File.read(@file) : ""
38
+ return false unless File.exist?(@file)
59
39
 
60
- /#{SKIP_ANNOTATION_PREFIX}.*/o.match?(file_string)
40
+ /#{SKIP_ANNOTATION_PREFIX}.*/o.match?(File.read(@file))
61
41
  end
62
42
  end
63
43
  end
@@ -11,8 +11,7 @@ module AnnotateRb
11
11
  # - "# status(a/b/c) :string not null"
12
12
  # - "# created_at :datetime not null"
13
13
  # - "# updated_at :datetime not null"
14
- COLUMN_PATTERN = /^#[\t ]+[\w*.`\[\]():]+(?:\(.*?\))?[\t ]+.+$/
15
-
14
+ COLUMN_PATTERN = /^#[\t ]+[[\p{L}\p{N}_]*.`\[\]():]+(?:\(.*?\))?[\t ]+.+$/
16
15
  class << self
17
16
  def call(file_content, annotation_block)
18
17
  new(file_content, annotation_block).generate
@@ -28,7 +28,7 @@ module AnnotateRb
28
28
  end
29
29
 
30
30
  cols = cols.sort_by(&:name) if @options[:sort]
31
- cols = classified_sort(cols) if @options[:classified_sort]
31
+ cols = classified_sort(cols, @options[:grouped_polymorphic]) if @options[:classified_sort]
32
32
 
33
33
  cols
34
34
  end
@@ -177,7 +177,7 @@ module AnnotateRb
177
177
  @position_of_column_comment ||= @options[:position_of_column_comment]
178
178
  end
179
179
 
180
- def classified_sort(cols)
180
+ def classified_sort(cols, grouped_polymorphic)
181
181
  rest_cols = []
182
182
  timestamps = []
183
183
  associations = []
@@ -186,6 +186,8 @@ module AnnotateRb
186
186
  # specs don't load defaults, so ensure we have defaults here
187
187
  timestamp_columns = @options[:timestamp_columns] || DEFAULT_TIMESTAMP_COLUMNS
188
188
 
189
+ col_names = cols.map(&:name)
190
+
189
191
  cols.each do |c|
190
192
  if c.name.eql?("id")
191
193
  id = c
@@ -193,6 +195,9 @@ module AnnotateRb
193
195
  timestamps << c
194
196
  elsif c.name[-3, 3].eql?("_id")
195
197
  associations << c
198
+ elsif c.name[-5, 5].eql?("_type") && col_names.include?(c.name.sub(/_type$/, "_id")) && grouped_polymorphic
199
+ # This is a polymorphic association's type column
200
+ associations << c
196
201
  else
197
202
  rest_cols << c
198
203
  end
@@ -41,6 +41,7 @@ module AnnotateRb
41
41
  format_rdoc: false, # ModelAnnotator
42
42
  format_yard: false, # ModelAnnotator
43
43
  frozen: false, # ModelAnnotator, but should be used by both
44
+ grouped_polymorphic: false, # ModelAnnotator
44
45
  ignore_model_sub_dir: false, # ModelAnnotator
45
46
  ignore_unknown_models: false, # ModelAnnotator
46
47
  include_version: false, # ModelAnnotator
@@ -113,6 +114,7 @@ module AnnotateRb
113
114
  :format_rdoc,
114
115
  :format_yard,
115
116
  :frozen,
117
+ :grouped_polymorphic,
116
118
  :ignore_model_sub_dir,
117
119
  :ignore_unknown_models,
118
120
  :include_version,
@@ -407,6 +407,11 @@ module AnnotateRb
407
407
  @options[:classified_sort] = true
408
408
  end
409
409
 
410
+ option_parser.on("--grouped-polymorphic",
411
+ "Group polymorphic associations together in the annotation when using --classified-sort") do
412
+ @options[:grouped_polymorphic] = true
413
+ end
414
+
410
415
  option_parser.on("-R",
411
416
  "--require path",
412
417
  "Additional file to require before loading models, may be used multiple times") do |path|
@@ -3,9 +3,23 @@
3
3
  module AnnotateRb
4
4
  class Runner
5
5
  class << self
6
+ attr_reader :runner
7
+
6
8
  def run(args)
7
- new.run(args)
9
+ self.runner = new
10
+
11
+ runner.run(args)
12
+
13
+ self.runner = nil
8
14
  end
15
+
16
+ def running?
17
+ !!runner
18
+ end
19
+
20
+ private
21
+
22
+ attr_writer :runner
9
23
  end
10
24
 
11
25
  def run(args)
@@ -18,7 +18,7 @@ if defined?(Rails::Application) && Rails.version.split(".").first.to_i >= 6
18
18
 
19
19
  # If there's multiple databases, this appends database specific rake tasks to `migration_tasks`
20
20
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |database_name|
21
- migration_tasks.concat(%w[db:migrate db:migrate:up db:migrate:down].map { |task| "#{task}:#{database_name}" })
21
+ migration_tasks.concat(%w[db:migrate db:migrate:up db:migrate:down db:rollback].map { |task| "#{task}:#{database_name}" })
22
22
  end
23
23
  end
24
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: annotaterb
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.17.0
4
+ version: 4.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew W. Lee
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-07-14 00:00:00.000000000 Z
11
+ date: 2025-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord