annotaterb 4.19.0 → 4.21.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: '0759110968217261a67bb8c519e55398ff9f43392e6cc4771bbebf5f97ce0395'
4
- data.tar.gz: d179acc1d279901b547475d5ee87d46346d671e083ef233d2e65e1a7c8d3f277
3
+ metadata.gz: d35263cf60a69ceabf708e6da1acb1aa7dbb9994028b36726d813a00ef0ec7f0
4
+ data.tar.gz: f7286ebed8b6b2c2d2c5edb78dbeaa89dc6052619c8631a7d5b299e76c13bd0e
5
5
  SHA512:
6
- metadata.gz: 8c0c8deaf4685925e3992f0adc33ecc2d92c49049eea38e44881d510b06128e031569ab242b80e160d534b369985a4eb9bb28612682d10c7a4e254f18030078e
7
- data.tar.gz: 1f37df086f3c6afd475e684bdc8458fd3ffe70ff245f2dc6b14786cd889e3b2107269064344f79c27425f46e0f599b3a6d3d4e7662844523c7a22bd799c49fc5
6
+ metadata.gz: fcd554627a6f477ae5120a98afde43b89f08aa6411ea64e2feba73f752b34499172a8bee267b7cf68f1fcd729a921e90738a6047c7f939239063cc2b935f95f3
7
+ data.tar.gz: 17ac0370bef28e3275368c7a0f93a74e0863042676656878ea94b69416d2a84ec39214f6368f70ff9c2ad2b45f1714488cb57235a8950fdfef3aa5c2ce9f315f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## [v4.20.0](https://github.com/drwl/annotaterb/tree/v4.20.0) (2025-10-20)
4
+
5
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.19.0...v4.20.0)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Bump version to v4.20.0 [\#278](https://github.com/drwl/annotaterb/pull/278) ([drwl](https://github.com/drwl))
10
+ - Bump github/codeql-action from 3 to 4 [\#277](https://github.com/drwl/annotaterb/pull/277) ([dependabot[bot]](https://github.com/apps/dependabot))
11
+ - fix: position-of-column-comment option [\#275](https://github.com/drwl/annotaterb/pull/275) ([JohnnyKei](https://github.com/JohnnyKei))
12
+ - feat: Add database name to annotations in multi-DB environments [\#272](https://github.com/drwl/annotaterb/pull/272) ([OdenTakashi](https://github.com/OdenTakashi))
13
+ - fix: resolve YAML syntax error in update\_config generator [\#269](https://github.com/drwl/annotaterb/pull/269) ([ivy](https://github.com/ivy))
14
+ - Update README.md [\#268](https://github.com/drwl/annotaterb/pull/268) ([torgoton](https://github.com/torgoton))
15
+ - Honor --frozen option in routes [\#265](https://github.com/drwl/annotaterb/pull/265) ([garriguv](https://github.com/garriguv))
16
+ - refactor\(test\): Default to single-DB environment for tests [\#264](https://github.com/drwl/annotaterb/pull/264) ([OdenTakashi](https://github.com/OdenTakashi))
17
+ - Escape column comment newlines when using "rightmost" value for position\_of\_column\_comment option [\#263](https://github.com/drwl/annotaterb/pull/263) ([rowanhogan](https://github.com/rowanhogan))
18
+ - chore: introduce switchable DB environment for specs [\#262](https://github.com/drwl/annotaterb/pull/262) ([OdenTakashi](https://github.com/OdenTakashi))
19
+ - Generate changelog for v4.19.0 [\#260](https://github.com/drwl/annotaterb/pull/260) ([drwl](https://github.com/drwl))
20
+ - Bump actions/checkout from 4 to 5 [\#257](https://github.com/drwl/annotaterb/pull/257) ([dependabot[bot]](https://github.com/apps/dependabot))
21
+
22
+ ## [v4.19.0](https://github.com/drwl/annotaterb/tree/v4.19.0) (2025-08-28)
23
+
24
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.18.0...v4.19.0)
25
+
26
+ **Implemented enhancements:**
27
+
28
+ - ignore ActiveRecord::AssociatedObject [\#172](https://github.com/drwl/annotaterb/issues/172)
29
+
30
+ **Closed issues:**
31
+
32
+ - STI classes blank [\#252](https://github.com/drwl/annotaterb/issues/252)
33
+ - Model annotation issue [\#249](https://github.com/drwl/annotaterb/issues/249)
34
+
35
+ **Merged pull requests:**
36
+
37
+ - Bump version to v4.19.0 [\#259](https://github.com/drwl/annotaterb/pull/259) ([drwl](https://github.com/drwl))
38
+ - Fix STI models not being annotated [\#256](https://github.com/drwl/annotaterb/pull/256) ([drwl](https://github.com/drwl))
39
+ - refactor: relocate migration\_version\_for\_model method to ModelWrapper [\#255](https://github.com/drwl/annotaterb/pull/255) ([OdenTakashi](https://github.com/OdenTakashi))
40
+ - Fix: Skip abstract models during annotation [\#253](https://github.com/drwl/annotaterb/pull/253) ([taise](https://github.com/taise))
41
+ - 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))
42
+ - Return a model files array even if it’s empty [\#248](https://github.com/drwl/annotaterb/pull/248) ([Flink](https://github.com/Flink))
43
+ - Generate changelog for v4.18.0 [\#247](https://github.com/drwl/annotaterb/pull/247) ([drwl](https://github.com/drwl))
44
+
3
45
  ## [v4.18.0](https://github.com/drwl/annotaterb/tree/v4.18.0) (2025-08-04)
4
46
 
5
47
  [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.17.0...v4.18.0)
data/README.md CHANGED
@@ -75,7 +75,7 @@ $ ANNOTATERB_SKIP_ON_DB_TASKS=1 bin/rails db:migrate
75
75
  The following Rails generator commands get added.
76
76
 
77
77
  ```sh
78
- $ bin/rails generator --help
78
+ $ bin/rails generate --help
79
79
 
80
80
  ...
81
81
 
@@ -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
@@ -183,6 +183,7 @@ Additional options that work for annotating models and routes
183
183
  --exclude Do not annotate fixtures, test files, factories, and/or serializers
184
184
  -f [bare|rdoc|yard|markdown], Render Schema Information as plain/RDoc/Yard/Markdown
185
185
  --format
186
+ --config_path [path] Path to configuration file (by default, .annotaterb.yml in the root of the project)
186
187
  -p [before|top|after|bottom], Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)
187
188
  --position
188
189
  --pc, --position-in-class [before|top|after|bottom]
@@ -211,6 +212,14 @@ Additional options that work for annotating models and routes
211
212
 
212
213
  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.
213
214
 
215
+ ### Configuration file location
216
+
217
+ AnnotateRb also supports other configuration file locations, and are searched for in the following locations (in order of precedence):
218
+ - `.annotaterb.yml`
219
+ - `config/annotaterb.yml`
220
+ - `.config/.annotaterb.yml`
221
+ - `.config/annotaterb/config.yml`
222
+
214
223
  ```yml
215
224
  # .annotaterb.yml
216
225
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.19.0
1
+ 4.21.0
@@ -1,20 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pathname"
4
+
3
5
  module AnnotateRb
4
6
  class ConfigFinder
5
7
  DOTFILE = ".annotaterb.yml"
6
8
 
7
9
  class << self
10
+ attr_accessor :config_path
11
+
8
12
  def find_project_root
9
13
  # We should expect this method to be called from a Rails project root and returning it
10
14
  # e.g. "/Users/drwl/personal/annotaterb/dummyapp"
11
- Dir.pwd
15
+ Pathname.pwd
12
16
  end
13
17
 
14
18
  def find_project_dotfile
15
- file_path = File.expand_path(DOTFILE, find_project_root)
19
+ return @config_path if @config_path && File.exist?(@config_path)
16
20
 
17
- return file_path if File.exist?(file_path)
21
+ [
22
+ find_project_root.join(DOTFILE),
23
+ find_project_root.join("config", DOTFILE.delete_prefix(".")),
24
+ find_project_root.join(".config", DOTFILE),
25
+ find_project_root.join(".config", "annotaterb", "config.yml")
26
+ ].find(&:exist?)
18
27
  end
19
28
  end
20
29
  end
@@ -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
@@ -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,
@@ -63,10 +64,23 @@ module AnnotateRb
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
72
+ end
73
+
74
+ private
75
+
76
+ def multi_db_environment?
77
+ return false if @options[:ignore_multi_database_name]
78
+
79
+ if defined?(::Rails) && ::Rails.env
80
+ ActiveRecord::Base.configurations.configs_for(env_name: ::Rails.env).size > 1
81
+ else
82
+ false
83
+ end
70
84
  end
71
85
  end
72
86
  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
@@ -23,6 +23,14 @@ module AnnotateRb
23
23
  body.map(&:to_markdown).join("\n")
24
24
  end
25
25
 
26
+ def to_rdoc
27
+ body.map(&:to_rdoc).join("\n")
28
+ end
29
+
30
+ def to_yard
31
+ body.map(&:to_yard).join("\n")
32
+ end
33
+
26
34
  def to_default
27
35
  body.map(&:to_default).join("\n")
28
36
  end
@@ -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",
@@ -23,6 +23,14 @@ module AnnotateRb
23
23
  body.map(&:to_markdown).join("\n")
24
24
  end
25
25
 
26
+ def to_rdoc
27
+ body.map(&:to_rdoc).join("\n")
28
+ end
29
+
30
+ def to_yard
31
+ body.map(&:to_yard).join("\n")
32
+ end
33
+
26
34
  def to_default
27
35
  body.map(&:to_default).join("\n")
28
36
  end
@@ -23,6 +23,14 @@ module AnnotateRb
23
23
  body.map(&:to_markdown).join("\n")
24
24
  end
25
25
 
26
+ def to_rdoc
27
+ body.map(&:to_rdoc).join("\n")
28
+ end
29
+
30
+ def to_yard
31
+ body.map(&:to_yard).join("\n")
32
+ end
33
+
26
34
  def to_default
27
35
  body.map(&:to_default).join("\n")
28
36
  end
@@ -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
@@ -228,8 +232,7 @@ module AnnotateRb
228
232
  # Multi-database support: Cache migration versions per database connection to handle
229
233
  # different schema versions across primary/secondary databases correctly.
230
234
  # Example: primary → "current_version_primary", secondary → "current_version_secondary"
231
- connection_pool_name = connection.pool.db_config.name
232
- cache_key = "current_version_#{connection_pool_name}".to_sym
235
+ cache_key = "current_version_#{database_name}".to_sym
233
236
 
234
237
  if @options.get_state(cache_key).nil?
235
238
  migration_version = begin
@@ -76,6 +76,7 @@ module AnnotateRb
76
76
  timestamp_columns: ModelAnnotator::ModelWrapper::DEFAULT_TIMESTAMP_COLUMNS,
77
77
 
78
78
  ignore_columns: nil, # ModelAnnotator
79
+ ignore_multi_database_name: false, # ModelAnnotator
79
80
  ignore_routes: nil, # RouteAnnotator
80
81
  ignore_unknown_models: false, # ModelAnnotator
81
82
  models: true, # Core
@@ -143,6 +144,7 @@ module AnnotateRb
143
144
  :ignore_columns,
144
145
  :ignore_routes,
145
146
  :ignore_unknown_models,
147
+ :ignore_multi_database_name,
146
148
  :models,
147
149
  :routes,
148
150
  :skip_on_db_migrate,
@@ -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",
@@ -436,6 +436,11 @@ module AnnotateRb
436
436
  "Render Schema Information as plain/RDoc/Yard/Markdown") do |format_type|
437
437
  @options["format_#{format_type}".to_sym] = true
438
438
  end
439
+
440
+ option_parser.on("--config-path [path]",
441
+ "Path to configuration file (by default, .annotaterb.yml in the root of the project)") do |path|
442
+ @options[:config_path] = path
443
+ end
439
444
  end
440
445
  end
441
446
  end
@@ -3,8 +3,9 @@
3
3
  module AnnotateRb
4
4
  class RakeBootstrapper
5
5
  class << self
6
- def call(options)
6
+ def call
7
7
  require "rake"
8
+
8
9
  load "./Rakefile" if File.exist?("./Rakefile") && !Rake::Task.task_defined?(:environment)
9
10
 
10
11
  begin
@@ -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
@@ -23,23 +23,23 @@ module AnnotateRb
23
23
  end
24
24
 
25
25
  def run(args)
26
- config_file_options = ConfigLoader.load_config
27
26
  parser = Parser.new(args, {})
28
27
 
29
28
  parsed_options = parser.parse
30
29
  remaining_args = parser.remaining_args
31
30
 
31
+ AnnotateRb::ConfigFinder.config_path = parsed_options[:config_path] if parsed_options[:config_path]
32
+ config_file_options = ConfigLoader.load_config
32
33
  options = config_file_options.merge(parsed_options)
33
34
 
34
35
  @options = Options.from(options, {working_args: remaining_args})
35
- AnnotateRb::RakeBootstrapper.call(@options)
36
+ AnnotateRb::RakeBootstrapper.call
36
37
 
37
- if @options[:command]
38
- @options[:command].call(@options)
39
- else
40
- # TODO
41
- raise "Didn't specify a command"
42
- end
38
+ raise "Didn't specify a command" unless @options[:command]
39
+
40
+ @options[:command].call(@options)
41
+
42
+ # TODO
43
43
  end
44
44
  end
45
45
  end
data/lib/annotate_rb.rb CHANGED
@@ -2,14 +2,11 @@
2
2
 
3
3
  require "active_record"
4
4
  require "active_support"
5
-
6
- # Helper.fallback depends on this being required because it adds #present? to nil
7
- require "active_support/core_ext/object/blank"
8
- require "active_support/core_ext/class/subclasses"
9
- require "active_support/core_ext/string/inflections"
10
-
11
5
  require "rake"
12
6
 
7
+ module AnnotateRb
8
+ end
9
+
13
10
  require_relative "annotate_rb/helper"
14
11
  require_relative "annotate_rb/core"
15
12
  require_relative "annotate_rb/commands"
@@ -23,6 +20,3 @@ require_relative "annotate_rb/rake_bootstrapper"
23
20
  require_relative "annotate_rb/config_finder"
24
21
  require_relative "annotate_rb/config_loader"
25
22
  require_relative "annotate_rb/config_generator"
26
-
27
- module AnnotateRb
28
- end
data/lib/annotaterb.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # Gem names that follow naming convention work seamlessly. However, this gem is "annotaterb" where in code it is
2
2
  # AnnotateRb. Because of this, we need this file so that the rest of the library automatically gets required.
3
3
 
4
- require "annotate_rb"
4
+ require_relative "annotate_rb"
@@ -4,5 +4,7 @@
4
4
  if Rails.env.development? && ENV["ANNOTATERB_SKIP_ON_DB_TASKS"].nil?
5
5
  require "annotate_rb"
6
6
 
7
+ # Can modify the config path here if needed - by default, it's .annotaterb.yml in the root of the project
8
+ # AnnotateRb::ConfigFinder.config_path = ""
7
9
  AnnotateRb::Core.load_rake_tasks
8
10
  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.19.0
4
+ version: 4.21.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-28 00:00:00.000000000 Z
11
+ date: 2026-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord