annotaterb 4.18.0 → 4.20.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: 0276a5044aa1b444f73aac5612004ce9a8c05c6d47634fb2e8798c24a442fed5
4
- data.tar.gz: 58cd27cb187989b06c459979ac0152db9dfdb54d671b9348980c244caa7981a6
3
+ metadata.gz: 9df7cea27e60968dc415cd65fc55696bfcb47444bdb0dc9964ce155bfbce4e40
4
+ data.tar.gz: 6883710db1dd58633c3a349adec97257df9c2d809a220fd19ba90c2a4a584cb7
5
5
  SHA512:
6
- metadata.gz: ac0f491e7022299fc96029950c5edf2b0e05aa38e9f3198ec37acbd04275888be493f4202f31295e8db0ad7737cc03d2c6b52e5fbb51c24418ef92f40da77a13
7
- data.tar.gz: 914216a38c137682acb6e2b58154c3af47dba3b0ebb424b69194a59c3939cfdd01c00d0f75a10bb51800f2ea6ce3f4dc97f3cdcd592ff7f77e7cafc906cd660f
6
+ metadata.gz: 2e164027db851243b7a1fccf9590c4a7515f47454ec785070e8e1dcd71bc0de7bec2caea30d919e6497dedfe78180681828cd6f1e24c6f0539c1d4e6b7895c33
7
+ data.tar.gz: 65629d818e0f3a92528deec50d5ba6adeb4a521058a174a7d463df1d565a8bf59eccd4ddb039ea68fe0dffed7329a994a5fbc1dae9cf19cb87cf9dcec7e308f2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # Changelog
2
2
 
3
+ ## [v4.19.0](https://github.com/drwl/annotaterb/tree/v4.19.0) (2025-08-28)
4
+
5
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.18.0...v4.19.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - ignore ActiveRecord::AssociatedObject [\#172](https://github.com/drwl/annotaterb/issues/172)
10
+
11
+ **Closed issues:**
12
+
13
+ - STI classes blank [\#252](https://github.com/drwl/annotaterb/issues/252)
14
+ - Model annotation issue [\#249](https://github.com/drwl/annotaterb/issues/249)
15
+
16
+ **Merged pull requests:**
17
+
18
+ - Bump version to v4.19.0 [\#259](https://github.com/drwl/annotaterb/pull/259) ([drwl](https://github.com/drwl))
19
+ - Fix STI models not being annotated [\#256](https://github.com/drwl/annotaterb/pull/256) ([drwl](https://github.com/drwl))
20
+ - refactor: relocate migration\_version\_for\_model method to ModelWrapper [\#255](https://github.com/drwl/annotaterb/pull/255) ([OdenTakashi](https://github.com/OdenTakashi))
21
+ - Fix: Skip abstract models during annotation [\#253](https://github.com/drwl/annotaterb/pull/253) ([taise](https://github.com/taise))
22
+ - Fix Ruby 3.3.8 compatibility and improve Zeitwerk support for non-Rails projects [\#250](https://github.com/drwl/annotaterb/pull/250) ([bradley2W1DL](https://github.com/bradley2W1DL))
23
+ - Return a model files array even if it’s empty [\#248](https://github.com/drwl/annotaterb/pull/248) ([Flink](https://github.com/Flink))
24
+ - Generate changelog for v4.18.0 [\#247](https://github.com/drwl/annotaterb/pull/247) ([drwl](https://github.com/drwl))
25
+
26
+ ## [v4.18.0](https://github.com/drwl/annotaterb/tree/v4.18.0) (2025-08-04)
27
+
28
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.17.0...v4.18.0)
29
+
30
+ **Implemented enhancements:**
31
+
32
+ - Feature request: support for multi database [\#188](https://github.com/drwl/annotaterb/issues/188)
33
+
34
+ **Closed issues:**
35
+
36
+ - Does not run on rollback with multiple databases [\#244](https://github.com/drwl/annotaterb/issues/244)
37
+ - classified\_sort and polymorphic associations [\#236](https://github.com/drwl/annotaterb/issues/236)
38
+ - --show-migration also annotates the primary DB's schema version for models referencing the secondary DB [\#233](https://github.com/drwl/annotaterb/issues/233)
39
+ - Annotations are not added on top of model files when columns'`comment:` contains Japanese characters in migrations [\#200](https://github.com/drwl/annotaterb/issues/200)
40
+ - Feature: further customization to achieve more compact annotations [\#150](https://github.com/drwl/annotaterb/issues/150)
41
+ - Version 5 change list [\#127](https://github.com/drwl/annotaterb/issues/127)
42
+ - Reformat Column Comments [\#117](https://github.com/drwl/annotaterb/issues/117)
43
+
44
+ **Merged pull requests:**
45
+
46
+ - Bump version to v4.18.0 [\#246](https://github.com/drwl/annotaterb/pull/246) ([drwl](https://github.com/drwl))
47
+ - Run on rollback in app with multiple databases [\#245](https://github.com/drwl/annotaterb/pull/245) ([z1lk](https://github.com/z1lk))
48
+ - Speed up AnnotationDecider [\#243](https://github.com/drwl/annotaterb/pull/243) ([DRBragg](https://github.com/DRBragg))
49
+ - Add AnnotateRb::Runner.running? method [\#242](https://github.com/drwl/annotaterb/pull/242) ([thewatts](https://github.com/thewatts))
50
+ - fix: --show-migration to use per-model database connections [\#241](https://github.com/drwl/annotaterb/pull/241) ([OdenTakashi](https://github.com/OdenTakashi))
51
+ - Fix: Support Japanese characters in column names [\#239](https://github.com/drwl/annotaterb/pull/239) ([tonystrawberry](https://github.com/tonystrawberry))
52
+ - Fix classified\_sort to group polymorphic association columns together [\#238](https://github.com/drwl/annotaterb/pull/238) ([garriguv](https://github.com/garriguv))
53
+ - Generate changelog for v4.17.0 [\#235](https://github.com/drwl/annotaterb/pull/235) ([drwl](https://github.com/drwl))
54
+
3
55
  ## [v4.17.0](https://github.com/drwl/annotaterb/tree/v4.17.0) (2025-07-14)
4
56
 
5
57
  [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.16.0...v4.17.0)
data/README.md CHANGED
@@ -146,10 +146,10 @@ Annotate model options:
146
146
  --ignore-unknown-models don't display warnings for bad model files
147
147
  -I, --ignore-columns REGEX don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`
148
148
  --with-comment include database comments in model annotations
149
- --without-comment include database comments in model annotations
149
+ --without-comment exclude database comments in model annotations
150
150
  --with-column-comments include column comments in model annotations
151
151
  --without-column-comments exclude column comments in model annotations
152
- --position-of-column-comments VALUE
152
+ --position-of-column-comment [with_name|rightmost_column]
153
153
  set the position, in the annotation block, of the column comment
154
154
  --with-table-comments include table comments in model annotations
155
155
  --without-table-comments exclude table comments in model annotations
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.18.0
1
+ 4.20.0
@@ -13,6 +13,9 @@ module AnnotateRb
13
13
  differences = defaults.keys - user_defaults.keys
14
14
  result = defaults.slice(*differences)
15
15
 
16
+ # Return empty string if no differences to avoid appending empty hash
17
+ return "" if result.empty?
18
+
16
19
  # Generates proper YAML including the leading hyphens `---` header
17
20
  yml_content = YAML.dump(result, StringIO.new).string
18
21
  # Remove the header
@@ -7,17 +7,16 @@ module AnnotateRb
7
7
  def call(options)
8
8
  options[:require].count > 0 && options[:require].each { |path| require path }
9
9
 
10
- if defined?(::Rails::Application)
11
- if defined?(::Zeitwerk)
12
- # Delegate to Zeitwerk to load stuff as needed
13
- else
14
- klass = ::Rails::Application.send(:subclasses).first
15
- klass.eager_load!
16
- end
10
+ if defined?(::Zeitwerk)
11
+ # Delegate to Zeitwerk to load stuff as needed
12
+ # (Supports both Rails and non-Rails applications)
13
+ elsif defined?(::Rails::Application)
14
+ klass = ::Rails::Application.send(:subclasses).first
15
+ klass.eager_load!
17
16
  else
18
17
  model_files = ModelAnnotator::ModelFilesGetter.call(options)
19
18
  model_files&.each do |model_file|
20
- require model_file
19
+ require File.join(*model_file)
21
20
  end
22
21
  end
23
22
  end
@@ -5,7 +5,7 @@ module AnnotateRb
5
5
  module Annotation
6
6
  class AnnotationBuilder
7
7
  class Annotation < Components::Base
8
- attr_reader :version, :table_name, :table_comment, :max_size
8
+ attr_reader :version, :table_name, :table_comment, :max_size, :database_name
9
9
 
10
10
  def initialize(options, **input)
11
11
  @options = options
@@ -15,12 +15,13 @@ module AnnotateRb
15
15
  @table_comment = input[:table_comment]
16
16
  @max_size = input[:max_size]
17
17
  @model = input[:model]
18
+ @database_name = input[:database_name]
18
19
  end
19
20
 
20
21
  def body
21
22
  [
22
23
  MainHeader.new(version, @options[:include_version]),
23
- SchemaHeader.new(table_name, table_comment, @options),
24
+ SchemaHeader.new(table_name, table_comment, database_name, @options),
24
25
  MarkdownHeader.new(max_size),
25
26
  *columns,
26
27
  IndexAnnotation::AnnotationBuilder.new(@model, @options).build,
@@ -59,38 +60,25 @@ module AnnotateRb
59
60
  end
60
61
 
61
62
  def build
62
- version = migration_version_for_model(@model)
63
+ version = @model.migration_version
63
64
  table_name = @model.table_name
64
65
  table_comment = @model.connection.try(:table_comment, @model.table_name)
65
66
  max_size = @model.max_schema_info_width
67
+ database_name = @model.database_name if multi_db_environment?
66
68
 
67
69
  _annotation = Annotation.new(@options,
68
70
  version: version, table_name: table_name, table_comment: table_comment,
69
- max_size: max_size, model: @model).build
71
+ max_size: max_size, model: @model, database_name: database_name).build
70
72
  end
71
73
 
72
74
  private
73
75
 
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)
76
+ def multi_db_environment?
77
+ if defined?(::Rails) && ::Rails.env
78
+ ActiveRecord::Base.configurations.configs_for(env_name: ::Rails.env).size > 1
79
+ else
80
+ false
91
81
  end
92
-
93
- @options.get_state(cache_key)
94
82
  end
95
83
  end
96
84
  end
@@ -20,11 +20,28 @@ module AnnotateRb
20
20
  end
21
21
  end
22
22
 
23
- attr_reader :table_name, :table_comment
23
+ class DatabaseName < Components::Base
24
+ attr_reader :name
25
+
26
+ def initialize(name)
27
+ @name = name
28
+ end
29
+
30
+ def to_default
31
+ "# Database name: #{name}"
32
+ end
33
+
34
+ def to_markdown
35
+ "# Database name: `#{name}`"
36
+ end
37
+ end
38
+
39
+ attr_reader :table_name, :table_comment, :database_name
24
40
 
25
- def initialize(table_name, table_comment, options)
41
+ def initialize(table_name, table_comment, database_name, options)
26
42
  @table_name = table_name
27
43
  @table_comment = table_comment
44
+ @database_name = database_name
28
45
  @options = options
29
46
  end
30
47
 
@@ -32,8 +49,9 @@ module AnnotateRb
32
49
  [
33
50
  Components::BlankCommentLine.new,
34
51
  TableName.new(name),
52
+ (DatabaseName.new(database_name) if database_name),
35
53
  Components::BlankCommentLine.new
36
- ]
54
+ ].compact
37
55
  end
38
56
 
39
57
  def to_default
@@ -16,17 +16,26 @@ 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?
20
19
 
21
- return @options[:exclude_sti_subclasses] ? klass.base_class? : true
20
+ return false unless klass.respond_to?(:descends_from_active_record?)
21
+
22
+ # Skip annotating STI classes
23
+ if @options[:exclude_sti_subclasses] && !klass.descends_from_active_record?
24
+ return false
25
+ end
26
+
27
+ return false if klass.abstract_class?
28
+ return false unless klass.table_exists?
29
+
30
+ return true
22
31
  rescue BadModelFileError => e
23
32
  unless @options[:ignore_unknown_models]
24
33
  warn "Unable to process #{@file}: #{e.message}"
25
- warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
34
+ warn "\t#{e.backtrace.join("\n\t")}" if @options[:trace]
26
35
  end
27
36
  rescue => e
28
37
  warn "Unable to process #{@file}: #{e.message}"
29
- warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
38
+ warn "\t#{e.backtrace.join("\n\t")}" if @options[:trace]
30
39
  end
31
40
 
32
41
  false
@@ -22,12 +22,16 @@ module AnnotateRb
22
22
  def name
23
23
  case position_of_column_comment
24
24
  when :with_name
25
- "#{column.name}(#{column.comment.gsub(/\n/, '\\n')})"
25
+ "#{column.name}(#{escaped_column_comment})"
26
26
  else
27
27
  column.name
28
28
  end
29
29
  end
30
30
 
31
+ def escaped_column_comment
32
+ column.comment.to_s.gsub(/\n/, '\\n')
33
+ end
34
+
31
35
  def to_rdoc
32
36
  # standard:disable Lint/FormatParameterMismatch
33
37
  format("# %-#{max_name_size}.#{max_name_size}s<tt>%s</tt>",
@@ -56,7 +60,7 @@ module AnnotateRb
56
60
  name_remainder = max_name_size - name.length - non_ascii_length(name)
57
61
  type_remainder = (MD_TYPE_ALLOWANCE - 2) - type.length
58
62
  attributes_remainder = max_attributes_size + 1 - joined_attributes.length
59
- comment_rightmost = (position_of_column_comment != :rightmost_column) ? "" : " | `#{@column.comment}`"
63
+ comment_rightmost = (position_of_column_comment != :rightmost_column) ? "" : " | `#{escaped_column_comment}`"
60
64
 
61
65
  # standard:disable Lint/FormatParameterMismatch
62
66
  format(
@@ -72,7 +76,7 @@ module AnnotateRb
72
76
  end
73
77
 
74
78
  def to_default
75
- comment_rightmost = (position_of_column_comment == :rightmost_column) ? @column.comment : ""
79
+ comment_rightmost = (position_of_column_comment == :rightmost_column) ? escaped_column_comment : ""
76
80
  joined_attributes = attributes.join(", ")
77
81
  format(
78
82
  "# %s:%s %s %s",
@@ -32,9 +32,8 @@ module AnnotateRb
32
32
  warn "Either specify models on the command line, or use the --model-dir option."
33
33
  warn "Call 'annotaterb --help' for more info."
34
34
  # exit 1 # TODO: Return exit code back to caller. Right now it messes up RSpec being able to run
35
- else
36
- model_files
37
35
  end
36
+ model_files
38
37
  end
39
38
 
40
39
  private
@@ -38,6 +38,10 @@ module AnnotateRb
38
38
  @klass.connection
39
39
  end
40
40
 
41
+ def database_name
42
+ connection.pool.db_config.name
43
+ end
44
+
41
45
  # Returns the unmodified model columns
42
46
  def raw_columns
43
47
  @raw_columns ||= @klass.columns
@@ -221,6 +225,28 @@ module AnnotateRb
221
225
  @klass.name.foreign_key.to_sym
222
226
  ]
223
227
  end
228
+
229
+ def migration_version
230
+ return 0 unless @options[:include_version]
231
+
232
+ # Multi-database support: Cache migration versions per database connection to handle
233
+ # different schema versions across primary/secondary databases correctly.
234
+ # Example: primary → "current_version_primary", secondary → "current_version_secondary"
235
+ connection_pool_name = connection.pool.db_config.name
236
+ cache_key = "current_version_#{connection_pool_name}".to_sym
237
+
238
+ if @options.get_state(cache_key).nil?
239
+ migration_version = begin
240
+ connection.migration_context.current_version
241
+ rescue
242
+ 0
243
+ end
244
+
245
+ @options.set_state(cache_key, migration_version)
246
+ end
247
+
248
+ @options.get_state(cache_key)
249
+ end
224
250
  end
225
251
  end
226
252
  end
@@ -246,9 +246,9 @@ module AnnotateRb
246
246
  @options[:with_column_comments] = false
247
247
  end
248
248
 
249
- option_parser.on("--position-of-column-comments VALUE",
249
+ option_parser.on("--position-of-column-comment [with_name|rightmost_column]",
250
250
  "set the position, in the annotation block, of the column comment") do |value|
251
- @options[:position_of_column_comments] = value.to_sym
251
+ @options[:position_of_column_comment] = value.to_sym
252
252
  end
253
253
 
254
254
  option_parser.on("--with-table-comments",
@@ -423,9 +423,9 @@ module AnnotateRb
423
423
  end
424
424
 
425
425
  option_parser.on("-e",
426
- "--exclude [tests,fixtures,factories,serializers]",
426
+ "--exclude [tests,fixtures,factories,serializers,sti_subclasses]",
427
427
  Array,
428
- "Do not annotate fixtures, test files, factories, and/or serializers") do |exclusions|
428
+ "Do not annotate fixtures, test files, factories, serializers, and/or sti subclasses") do |exclusions|
429
429
  exclusions ||= EXCLUSION_LIST
430
430
  exclusions.each { |exclusion| @options["exclude_#{exclusion}".to_sym] = true }
431
431
  end
@@ -26,6 +26,10 @@ module AnnotateRb
26
26
  if existing_text == new_text
27
27
  false
28
28
  else
29
+ if options[:frozen]
30
+ abort "AnnotateRb error. #{routes_file} needs to be updated, but annotaterb was run with `--frozen`."
31
+ end
32
+
29
33
  write(new_text)
30
34
  true
31
35
  end
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.18.0
4
+ version: 4.20.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-08-04 00:00:00.000000000 Z
11
+ date: 2025-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord