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 +4 -4
- data/CHANGELOG.md +29 -0
- data/README.md +34 -5
- data/VERSION +1 -1
- data/lib/annotate_rb/model_annotator/annotation/annotation_builder.rb +25 -11
- data/lib/annotate_rb/model_annotator/annotation_decider.rb +4 -24
- data/lib/annotate_rb/model_annotator/annotation_diff_generator.rb +1 -2
- data/lib/annotate_rb/model_annotator/model_wrapper.rb +7 -2
- data/lib/annotate_rb/options.rb +2 -0
- data/lib/annotate_rb/parser.rb +5 -0
- data/lib/annotate_rb/runner.rb +15 -1
- data/lib/annotate_rb/tasks/annotate_models_migrate.rake +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0276a5044aa1b444f73aac5612004ce9a8c05c6d47634fb2e8798c24a442fed5
|
4
|
+
data.tar.gz: 58cd27cb187989b06c459979ac0152db9dfdb54d671b9348980c244caa7981a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
[](https://github.com/drwl/annotaterb/actions/workflows/ci.yml)
|
8
10
|
[](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
|
-
--
|
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.
|
1
|
+
4.18.0
|
@@ -59,17 +59,7 @@ module AnnotateRb
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def build
|
62
|
-
|
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
|
-
|
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
|
-
|
38
|
+
return false unless File.exist?(@file)
|
59
39
|
|
60
|
-
/#{SKIP_ANNOTATION_PREFIX}.*/o.match?(
|
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 ]+[\
|
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
|
data/lib/annotate_rb/options.rb
CHANGED
@@ -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,
|
data/lib/annotate_rb/parser.rb
CHANGED
@@ -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|
|
data/lib/annotate_rb/runner.rb
CHANGED
@@ -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
|
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.
|
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-
|
11
|
+
date: 2025-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|