annotaterb 4.4.1 → 4.5.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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +29 -0
  4. data/VERSION +1 -1
  5. data/lib/annotate_rb/config_generator.rb +28 -0
  6. data/lib/annotate_rb/model_annotator/annotated_file/generator.rb +49 -0
  7. data/lib/annotate_rb/model_annotator/annotated_file/updater.rb +46 -0
  8. data/lib/annotate_rb/model_annotator/annotated_file.rb +10 -0
  9. data/lib/annotate_rb/model_annotator/annotation_pattern_generator.rb +1 -1
  10. data/lib/annotate_rb/model_annotator/annotator.rb +2 -2
  11. data/lib/annotate_rb/model_annotator/file_components.rb +2 -2
  12. data/lib/annotate_rb/model_annotator/file_parser/magic_comment_parser.rb +34 -0
  13. data/lib/annotate_rb/model_annotator/file_parser.rb +9 -0
  14. data/lib/annotate_rb/model_annotator/model_files_getter.rb +4 -8
  15. data/lib/annotate_rb/model_annotator/model_wrapper.rb +1 -1
  16. data/lib/annotate_rb/model_annotator/pattern_getter.rb +2 -0
  17. data/lib/annotate_rb/model_annotator/single_file_annotator.rb +3 -4
  18. data/lib/annotate_rb/model_annotator/single_file_annotator_instruction.rb +1 -1
  19. data/lib/annotate_rb/model_annotator/single_file_remove_annotation_instruction.rb +1 -1
  20. data/lib/annotate_rb/model_annotator.rb +2 -2
  21. data/lib/annotate_rb/options.rb +4 -0
  22. data/lib/annotate_rb/parser.rb +9 -3
  23. data/lib/annotate_rb/runner.rb +5 -4
  24. data/lib/annotate_rb.rb +1 -0
  25. data/lib/generators/annotate_rb/config/USAGE +6 -0
  26. data/lib/generators/annotate_rb/config/config_generator.rb +15 -0
  27. data/lib/generators/annotate_rb/hook/USAGE +7 -0
  28. data/lib/generators/annotate_rb/hook/hook_generator.rb +15 -0
  29. data/lib/generators/annotate_rb/install/install_generator.rb +3 -4
  30. data/lib/generators/annotate_rb/update_config/USAGE +6 -0
  31. data/lib/generators/annotate_rb/update_config/update_config_generator.rb +15 -0
  32. metadata +15 -5
  33. data/lib/annotate_rb/model_annotator/file_builder.rb +0 -57
  34. data/lib/annotate_rb/model_annotator/magic_comment_parser.rb +0 -32
  35. /data/lib/generators/annotate_rb/{install → hook}/templates/annotate_rb.rake +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a337f543f32142efaffbfd396196692d42a98438352b3bdd406c104c25a9958a
4
- data.tar.gz: 27d091e7fed5953ccdd26c4b4874e45a0fcff541630595fa467e010629efb9ba
3
+ metadata.gz: ab5413ba1fb4c02274c37e7629b0553deed339067624ef96e1ad9a59ecf726d1
4
+ data.tar.gz: 6439540d1c152651735313e80839acddc79d202d8b0171edb6c424e932dde37a
5
5
  SHA512:
6
- metadata.gz: 44125b3f65246ad1b5a0dd0d354487462ea6584c6147165650268244fd8d3c9826cf337873f24c31e008efa1c560b37bcb71e36af7fc05c9bc381d48e2b1e4b0
7
- data.tar.gz: 7979e2309e3c09ee11fc090a424e7006a94634c7a970fe34b61028b3a90d495b684cc2a4a6fa78221b288dfe5e6682567835fb6839ada3903dfaa599a4f8cfdc
6
+ metadata.gz: 40353034b577b5a44a1204edbb02e25d01b4d99efcb8de1a50fd8698981767c4f5444079b851441db60d16c175237e63f80453370f38007613aae1da5b613f71
7
+ data.tar.gz: 5edb0a811149b9187fd0b2066cf1843a84fde281239e2628ba643fa1ce4c906e914b387d4f461e62c84d5323e21a51223f3d5e838f5f4da300743180d6dabb8e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [v4.4.1](https://github.com/drwl/annotaterb/tree/v4.4.1) (2023-09-11)
4
+
5
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.4.0...v4.4.1)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Bump version to v4.4.1 [\#62](https://github.com/drwl/annotaterb/pull/62) ([drwl](https://github.com/drwl))
10
+ - Fix annotation for columns with `Date` and `DateTime` default values [\#61](https://github.com/drwl/annotaterb/pull/61) ([drwl](https://github.com/drwl))
11
+ - Add integration tests [\#60](https://github.com/drwl/annotaterb/pull/60) ([drwl](https://github.com/drwl))
12
+ - Fix the default array value from being escaped [\#58](https://github.com/drwl/annotaterb/pull/58) ([drwl](https://github.com/drwl))
13
+ - Update dummyapp Rails version [\#56](https://github.com/drwl/annotaterb/pull/56) ([drwl](https://github.com/drwl))
14
+ - Bump puma from 5.6.5 to 6.3.1 in /dummyapp [\#55](https://github.com/drwl/annotaterb/pull/55) ([dependabot[bot]](https://github.com/apps/dependabot))
15
+ - Generate changelog for v4.4.0 [\#53](https://github.com/drwl/annotaterb/pull/53) ([drwl](https://github.com/drwl))
16
+ - Add CLI specs using `aruba` gem [\#43](https://github.com/drwl/annotaterb/pull/43) ([drwl](https://github.com/drwl))
17
+
3
18
  ## [v4.4.0](https://github.com/drwl/annotaterb/tree/v4.4.0) (2023-06-24)
4
19
 
5
20
  [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.3.1...v4.4.0)
data/README.md CHANGED
@@ -65,6 +65,35 @@ To skip the automatic annotation that happens after a db task, pass the environm
65
65
  $ ANNOTATERB_SKIP_ON_DB_TASKS=1 bin/rails db:migrate
66
66
  ```
67
67
 
68
+ ### Added Rails generators
69
+ The following Rails generator commands get added.
70
+
71
+ ```sh
72
+ $ bin/rails generator --help
73
+
74
+ ...
75
+
76
+ AnnotateRb:
77
+ annotate_rb:config
78
+ annotate_rb:hook
79
+ annotate_rb:install
80
+ annotate_rb:update_config
81
+ ...
82
+
83
+ ```
84
+
85
+ `bin/rails g annotate_rb:config`
86
+ - Generates a new configuration file, `.annotaterb.yml`, using defaults from the gem.
87
+
88
+ `bin/rails g annotate_rb:hook`
89
+ - 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
+
91
+ `bin/rails g annotate_rb:install`
92
+ - Runs the `config` and `hook` generator commands
93
+
94
+ `bin/rails g annotate_rb:update_config`
95
+ - 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
+
68
97
  ## Migrating from the annotate gem
69
98
  Refer to the [migration guide](MIGRATION_GUIDE.md).
70
99
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.4.1
1
+ 4.5.0
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ class ConfigGenerator
5
+ class << self
6
+ # Returns unset configuration key-value pairs as yaml.
7
+ # Useful when a config file was generated an older version of gem and new
8
+ # settings get added.
9
+ def unset_config_defaults
10
+ user_defaults = ConfigLoader.load_config
11
+ defaults = Options.from({}, {}).to_h
12
+
13
+ differences = defaults.keys - user_defaults.keys
14
+ result = defaults.slice(*differences)
15
+
16
+ # Generates proper YAML including the leading hyphens `---` header
17
+ yml_content = YAML.dump(result, StringIO.new).string
18
+ # Remove the header
19
+ yml_content.sub("---", "")
20
+ end
21
+
22
+ def default_config_yml
23
+ defaults_hash = Options.from({}, {}).to_h
24
+ _yml_content = YAML.dump(defaults_hash, StringIO.new).string
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module AnnotatedFile
6
+ # Generates the file with fresh annotations
7
+ class Generator
8
+ def initialize(file_components, annotation_position, options)
9
+ @file_components = file_components
10
+ @annotation_position = annotation_position
11
+ @options = options
12
+
13
+ @new_wrapped_annotations = wrapped_content(@file_components.new_annotations)
14
+ end
15
+
16
+ def generate
17
+ # Need to keep `.to_s` for now since the it can be either a String or Symbol
18
+ annotation_write_position = @options[@annotation_position].to_s
19
+
20
+ _content = if %w[after bottom].include?(annotation_write_position)
21
+ @file_components.magic_comments + (@file_components.pure_file_content.rstrip + "\n\n" + @new_wrapped_annotations)
22
+ elsif @file_components.magic_comments.empty?
23
+ @file_components.magic_comments + @new_wrapped_annotations + @file_components.pure_file_content.lstrip
24
+ else
25
+ @file_components.magic_comments + "\n" + @new_wrapped_annotations + @file_components.pure_file_content.lstrip
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def wrapped_content(content)
32
+ wrapper_open = if @options[:wrapper_open]
33
+ "# #{@options[:wrapper_open]}\n"
34
+ else
35
+ ""
36
+ end
37
+
38
+ wrapper_close = if @options[:wrapper_close]
39
+ "# #{@options[:wrapper_close]}\n"
40
+ else
41
+ ""
42
+ end
43
+
44
+ _wrapped_info_block = "#{wrapper_open}#{content}#{wrapper_close}"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module AnnotatedFile
6
+ # Updates existing annotations
7
+ class Updater
8
+ def initialize(file_components, annotation_position, options)
9
+ @file_components = file_components
10
+ @annotation_position = annotation_position
11
+ @options = options
12
+
13
+ @new_wrapped_annotations = wrapped_content(@file_components.new_annotations)
14
+ end
15
+
16
+ def update
17
+ return "" if !@file_components.has_annotations?
18
+
19
+ annotation_pattern = AnnotationPatternGenerator.call(@options)
20
+
21
+ new_annotation = @file_components.space_before_annotation + @new_wrapped_annotations + @file_components.space_after_annotation
22
+
23
+ _content = @file_components.current_file_content.sub(annotation_pattern, new_annotation)
24
+ end
25
+
26
+ private
27
+
28
+ def wrapped_content(content)
29
+ wrapper_open = if @options[:wrapper_open]
30
+ "# #{@options[:wrapper_open]}\n"
31
+ else
32
+ ""
33
+ end
34
+
35
+ wrapper_close = if @options[:wrapper_close]
36
+ "# #{@options[:wrapper_close]}\n"
37
+ else
38
+ ""
39
+ end
40
+
41
+ _wrapped_info_block = "#{wrapper_open}#{content}#{wrapper_close}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module AnnotatedFile
6
+ autoload :Generator, "annotate_rb/model_annotator/annotated_file/generator"
7
+ autoload :Updater, "annotate_rb/model_annotator/annotated_file/updater"
8
+ end
9
+ end
10
+ end
@@ -7,7 +7,7 @@ module AnnotateRb
7
7
  COMPAT_PREFIX_MD = "## Schema Info"
8
8
 
9
9
  class << self
10
- def call(options = Options.from({}))
10
+ def call(options)
11
11
  if options[:wrapper_open]
12
12
  return /(?:^(\n|\r\n)?# (?:#{options[:wrapper_open]}).*(\n|\r\n)?# (?:#{COMPAT_PREFIX}|#{COMPAT_PREFIX_MD}).*?(\n|\r\n)(#.*(\n|\r\n))*(\n|\r\n)*)|^(\n|\r\n)?# (?:#{COMPAT_PREFIX}|#{COMPAT_PREFIX_MD}).*?(\n|\r\n)(#.*(\n|\r\n))*(\n|\r\n)*/
13
13
  end
@@ -4,11 +4,11 @@ module AnnotateRb
4
4
  module ModelAnnotator
5
5
  class Annotator
6
6
  class << self
7
- def do_annotations(options = {})
7
+ def do_annotations(options)
8
8
  new(options).do_annotations
9
9
  end
10
10
 
11
- def remove_annotations(options = {})
11
+ def remove_annotations(options)
12
12
  new(options).remove_annotations
13
13
  end
14
14
  end
@@ -43,7 +43,7 @@ module AnnotateRb
43
43
  def pure_file_content
44
44
  @pure_file_content ||=
45
45
  begin
46
- content_without_magic_comments = @file_content.gsub(MagicCommentParser::MAGIC_COMMENTS_REGEX, "")
46
+ content_without_magic_comments = @file_content.gsub(FileParser::MagicCommentParser::MAGIC_COMMENTS_REGEX, "")
47
47
  content_without_annotations = content_without_magic_comments.sub(@annotation_pattern, "")
48
48
 
49
49
  content_without_annotations
@@ -51,7 +51,7 @@ module AnnotateRb
51
51
  end
52
52
 
53
53
  def magic_comments
54
- @magic_comments ||= MagicCommentParser.call(@file_content)
54
+ @magic_comments ||= FileParser::MagicCommentParser.call(@file_content)
55
55
  end
56
56
 
57
57
  def has_skip_string?
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module FileParser
6
+ # Extracts magic comments strings and returns them
7
+ class MagicCommentParser
8
+ MAGIC_COMMENTS = [
9
+ HASH_ENCODING = /(^#\s*encoding:.*(?:\n|r\n))/,
10
+ HASH_CODING = /(^# coding:.*(?:\n|\r\n))/,
11
+ HASH_FROZEN_STRING = /(^#\s*frozen_string_literal:.+(?:\n|\r\n))/,
12
+ STAR_ENCODING = /(^# -\*- encoding\s?:.*(?:\n|\r\n))/,
13
+ STAR_CODING = /(^# -\*- coding:.*(?:\n|\r\n))/,
14
+ STAR_FROZEN_STRING = /(^# -\*- frozen_string_literal\s*:.+-\*-(?:\n|\r\n))/,
15
+ SORBET_TYPED_STRING = /(^#\s*typed:.*(?:\n|r\n))/.freeze
16
+ ].freeze
17
+
18
+ MAGIC_COMMENTS_REGEX = Regexp.union(*MAGIC_COMMENTS).freeze
19
+
20
+ class << self
21
+ def call(content)
22
+ magic_comments = content.scan(MAGIC_COMMENTS_REGEX).flatten.compact
23
+
24
+ if magic_comments.any?
25
+ magic_comments.join
26
+ else
27
+ ""
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module FileParser
6
+ autoload :MagicCommentParser, "annotate_rb/model_annotator/file_parser/magic_comment_parser"
7
+ end
8
+ end
9
+ end
@@ -9,13 +9,9 @@ module AnnotateRb
9
9
  # of model files from root dir. Otherwise we take all the model files
10
10
  # in the model_dir directory.
11
11
  def call(options)
12
- model_files = []
12
+ model_files = list_model_files_from_argument(options)
13
13
 
14
- # Note: This is currently broken as we don't set `is_rake` anywhere.
15
- # It's an artifact from the old Annotate gem and how it did control flow.
16
- model_files = list_model_files_from_argument(options) if !options[:is_rake]
17
-
18
- return model_files if !model_files.empty?
14
+ return model_files if model_files.any?
19
15
 
20
16
  options[:model_dir].each do |dir|
21
17
  Dir.chdir(dir) do
@@ -41,9 +37,9 @@ module AnnotateRb
41
37
  private
42
38
 
43
39
  def list_model_files_from_argument(options)
44
- return [] if ARGV.empty?
40
+ return [] if options.get_state(:working_args).empty?
45
41
 
46
- specified_files = ARGV.map { |file| File.expand_path(file) }
42
+ specified_files = options.get_state(:working_args).map { |file| File.expand_path(file) }
47
43
 
48
44
  model_files = options[:model_dir].flat_map do |dir|
49
45
  absolute_dir_path = File.expand_path(dir)
@@ -6,7 +6,7 @@ module AnnotateRb
6
6
  # Should be the wrapper for an ActiveRecord model that serves as the source of truth of the model
7
7
  # of the model that we're annotating
8
8
 
9
- def initialize(klass, options = {})
9
+ def initialize(klass, options)
10
10
  @klass = klass
11
11
  @options = options
12
12
  end
@@ -142,6 +142,8 @@ module AnnotateRb
142
142
  File.join(root_directory, FilePatterns::FACTORY_BOT_SPEC_DIR, "%TABLE_NAME%.rb"), # (new style)
143
143
  File.join(root_directory, FilePatterns::FACTORY_BOT_TEST_DIR, "%PLURALIZED_MODEL_NAME%.rb"), # (new style)
144
144
  File.join(root_directory, FilePatterns::FACTORY_BOT_SPEC_DIR, "%PLURALIZED_MODEL_NAME%.rb"), # (new style)
145
+ File.join(root_directory, FilePatterns::FACTORY_BOT_TEST_DIR, "%PLURALIZED_MODEL_NAME%_factory.rb"), # (new style)
146
+ File.join(root_directory, FilePatterns::FACTORY_BOT_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_factory.rb"), # (new style)
145
147
  File.join(root_directory, FilePatterns::FABRICATORS_TEST_DIR, "%MODEL_NAME%_fabricator.rb"),
146
148
  File.join(root_directory, FilePatterns::FABRICATORS_SPEC_DIR, "%MODEL_NAME%_fabricator.rb")
147
149
  ]
@@ -21,12 +21,11 @@ module AnnotateRb
21
21
  # :position_in_*<Symbol>:: where to place the annotated section in fixture or model file,
22
22
  # :before, :top, :after or :bottom. Default is :before.
23
23
  #
24
- def call(file_name, annotation, annotation_position, options = {})
24
+ def call(file_name, annotation, annotation_position, options)
25
25
  return false unless File.exist?(file_name)
26
26
  old_content = File.read(file_name)
27
27
 
28
28
  file_components = FileComponents.new(old_content, annotation, options)
29
- builder = FileBuilder.new(file_components, annotation_position, options)
30
29
 
31
30
  return false if file_components.has_skip_string?
32
31
  return false if !file_components.annotations_changed? && !options[:force]
@@ -34,9 +33,9 @@ module AnnotateRb
34
33
  abort "AnnotateRb error. #{file_name} needs to be updated, but annotaterb was run with `--frozen`." if options[:frozen]
35
34
 
36
35
  updated_file_content = if !file_components.has_annotations? || options[:force]
37
- builder.generate_content_with_new_annotations
36
+ AnnotatedFile::Generator.new(file_components, annotation_position, options).generate
38
37
  else
39
- builder.update_existing_annotations
38
+ AnnotatedFile::Updater.new(file_components, annotation_position, options).update
40
39
  end
41
40
 
42
41
  File.open(file_name, "wb") { |f| f.puts updated_file_content }
@@ -4,7 +4,7 @@ module AnnotateRb
4
4
  module ModelAnnotator
5
5
  # A plain old Ruby object (PORO) that contains all necessary information for SingleFileAnnotator
6
6
  class SingleFileAnnotatorInstruction
7
- def initialize(file, annotation, position, options = {})
7
+ def initialize(file, annotation, position, options)
8
8
  @file = file # Path to file
9
9
  @annotation = annotation # Annotation string
10
10
  @position = position # Position in the file where to write the annotation to
@@ -4,7 +4,7 @@ module AnnotateRb
4
4
  module ModelAnnotator
5
5
  # A plain old Ruby object (PORO) that contains all necessary information for SingleFileAnnotationRemover
6
6
  class SingleFileRemoveAnnotationInstruction
7
- def initialize(file, options = {})
7
+ def initialize(file, options)
8
8
  @file = file # Path to file
9
9
  @options = options
10
10
  end
@@ -22,10 +22,10 @@ module AnnotateRb
22
22
  autoload :SingleFileRemoveAnnotationInstruction, "annotate_rb/model_annotator/single_file_remove_annotation_instruction"
23
23
  autoload :AnnotationDiffGenerator, "annotate_rb/model_annotator/annotation_diff_generator"
24
24
  autoload :AnnotationDiff, "annotate_rb/model_annotator/annotation_diff"
25
- autoload :FileBuilder, "annotate_rb/model_annotator/file_builder"
26
- autoload :MagicCommentParser, "annotate_rb/model_annotator/magic_comment_parser"
27
25
  autoload :FileComponents, "annotate_rb/model_annotator/file_components"
28
26
  autoload :ProjectAnnotator, "annotate_rb/model_annotator/project_annotator"
29
27
  autoload :ProjectAnnotationRemover, "annotate_rb/model_annotator/project_annotation_remover"
28
+ autoload :AnnotatedFile, "annotate_rb/model_annotator/annotated_file"
29
+ autoload :FileParser, "annotate_rb/model_annotator/file_parser"
30
30
  end
31
31
  end
@@ -210,5 +210,9 @@ module AnnotateRb
210
210
  def get_state(key)
211
211
  @state[key]
212
212
  end
213
+
214
+ def print
215
+ # TODO: prints options and state
216
+ end
213
217
  end
214
218
  end
@@ -3,7 +3,7 @@ require "optparse"
3
3
  module AnnotateRb
4
4
  # Class for handling command line arguments
5
5
  class Parser # rubocop:disable Metrics/ClassLength
6
- def self.parse(args, existing_options = {})
6
+ def self.parse(args, existing_options)
7
7
  new(args, existing_options).parse
8
8
  end
9
9
 
@@ -35,11 +35,11 @@ module AnnotateRb
35
35
  }.freeze
36
36
 
37
37
  def initialize(args, existing_options)
38
- @args = args
38
+ @args = args.clone
39
39
  base_options = DEFAULT_OPTIONS.dup
40
40
  @options = base_options.merge(existing_options)
41
41
  @commands = []
42
- @options[:original_args] = args.dup
42
+ @options[:original_args] = args.clone
43
43
  end
44
44
 
45
45
  def parse
@@ -52,6 +52,12 @@ module AnnotateRb
52
52
  @options
53
53
  end
54
54
 
55
+ def remaining_args
56
+ # `@args` gets modified throughout the lifecycle of this class.
57
+ # It starts as a shallow clone of ARGV, then arguments matching commands and options are removed in #parse
58
+ @args
59
+ end
60
+
55
61
  private
56
62
 
57
63
  def parse_command(args)
@@ -9,14 +9,15 @@ module AnnotateRb
9
9
  end
10
10
 
11
11
  def run(args)
12
- _original_args = args.dup
13
-
14
12
  config_file_options = ConfigLoader.load_config
15
- parsed_options = Parser.parse(args)
13
+ parser = Parser.new(args, {})
14
+
15
+ parsed_options = parser.parse
16
+ remaining_args = parser.remaining_args
16
17
 
17
18
  options = config_file_options.merge(parsed_options)
18
19
 
19
- @options = Options.from(options, {})
20
+ @options = Options.from(options, {working_args: remaining_args})
20
21
  AnnotateRb::RakeBootstrapper.call(@options)
21
22
 
22
23
  if @options[:command]
data/lib/annotate_rb.rb CHANGED
@@ -22,6 +22,7 @@ require_relative "annotate_rb/eager_loader"
22
22
  require_relative "annotate_rb/rake_bootstrapper"
23
23
  require_relative "annotate_rb/config_finder"
24
24
  require_relative "annotate_rb/config_loader"
25
+ require_relative "annotate_rb/config_generator"
25
26
 
26
27
  module AnnotateRb
27
28
  end
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Generates a default configuration file, `.annotaterb.yml` in your
3
+ Rails app project root.
4
+
5
+ Example:
6
+ `rails generate annotate_rb:config`
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "annotate_rb"
4
+
5
+ module AnnotateRb
6
+ module Generators
7
+ class ConfigGenerator < ::Rails::Generators::Base
8
+ def generate_config
9
+ create_file ::AnnotateRb::ConfigFinder::DOTFILE do
10
+ ::AnnotateRb::ConfigGenerator.default_config_yml
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ Description:
2
+ Adds a rake task into your Rails app's lib/tasks directory, that
3
+ automatically annotates models when you do a db:migrate in
4
+ development mode.
5
+
6
+ Example:
7
+ `rails generate annotate_rb:hook`
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "annotate_rb"
4
+
5
+ module AnnotateRb
6
+ module Generators
7
+ class HookGenerator < ::Rails::Generators::Base
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def copy_hook_file
11
+ copy_file "annotate_rb.rake", "lib/tasks/annotate_rb.rake"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -5,10 +5,9 @@ require "annotate_rb"
5
5
  module AnnotateRb
6
6
  module Generators
7
7
  class InstallGenerator < ::Rails::Generators::Base
8
- source_root File.expand_path("templates", __dir__)
9
-
10
- def copy_task
11
- copy_file "annotate_rb.rake", "lib/tasks/annotate_rb.rake"
8
+ def install_hook_and_generate_defaults
9
+ generate "annotate_rb:hook"
10
+ generate "annotate_rb:config"
12
11
  end
13
12
  end
14
13
  end
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Appends to .annotaterb.yml any missing default configuration
3
+ key-value pairs.
4
+
5
+ Example:
6
+ `rails generate annotate_rb:update_config`
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "annotate_rb"
4
+
5
+ module AnnotateRb
6
+ module Generators
7
+ class UpdateConfigGenerator < ::Rails::Generators::Base
8
+ def generate_config
9
+ insert_into_file ::AnnotateRb::ConfigFinder::DOTFILE do
10
+ ::AnnotateRb::ConfigGenerator.unset_config_defaults
11
+ end
12
+ end
13
+ end
14
+ end
15
+ 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.4.1
4
+ version: 4.5.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: 2023-09-11 00:00:00.000000000 Z
11
+ date: 2024-02-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Annotates Rails/ActiveRecord Models, routes, fixtures, and others based
14
14
  on the database schema.
@@ -31,11 +31,15 @@ files:
31
31
  - lib/annotate_rb/commands/print_help.rb
32
32
  - lib/annotate_rb/commands/print_version.rb
33
33
  - lib/annotate_rb/config_finder.rb
34
+ - lib/annotate_rb/config_generator.rb
34
35
  - lib/annotate_rb/config_loader.rb
35
36
  - lib/annotate_rb/core.rb
36
37
  - lib/annotate_rb/eager_loader.rb
37
38
  - lib/annotate_rb/helper.rb
38
39
  - lib/annotate_rb/model_annotator.rb
40
+ - lib/annotate_rb/model_annotator/annotated_file.rb
41
+ - lib/annotate_rb/model_annotator/annotated_file/generator.rb
42
+ - lib/annotate_rb/model_annotator/annotated_file/updater.rb
39
43
  - lib/annotate_rb/model_annotator/annotation_builder.rb
40
44
  - lib/annotate_rb/model_annotator/annotation_decider.rb
41
45
  - lib/annotate_rb/model_annotator/annotation_diff.rb
@@ -49,14 +53,14 @@ files:
49
53
  - lib/annotate_rb/model_annotator/column_annotation/column_wrapper.rb
50
54
  - lib/annotate_rb/model_annotator/column_annotation/default_value_builder.rb
51
55
  - lib/annotate_rb/model_annotator/column_annotation/type_builder.rb
52
- - lib/annotate_rb/model_annotator/file_builder.rb
53
56
  - lib/annotate_rb/model_annotator/file_components.rb
54
57
  - lib/annotate_rb/model_annotator/file_name_resolver.rb
58
+ - lib/annotate_rb/model_annotator/file_parser.rb
59
+ - lib/annotate_rb/model_annotator/file_parser/magic_comment_parser.rb
55
60
  - lib/annotate_rb/model_annotator/foreign_key_annotation.rb
56
61
  - lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder.rb
57
62
  - lib/annotate_rb/model_annotator/index_annotation.rb
58
63
  - lib/annotate_rb/model_annotator/index_annotation/annotation_builder.rb
59
- - lib/annotate_rb/model_annotator/magic_comment_parser.rb
60
64
  - lib/annotate_rb/model_annotator/model_class_getter.rb
61
65
  - lib/annotate_rb/model_annotator/model_files_getter.rb
62
66
  - lib/annotate_rb/model_annotator/model_wrapper.rb
@@ -80,9 +84,15 @@ files:
80
84
  - lib/annotate_rb/route_annotator/removal_processor.rb
81
85
  - lib/annotate_rb/runner.rb
82
86
  - lib/annotate_rb/tasks/annotate_models_migrate.rake
87
+ - lib/generators/annotate_rb/config/USAGE
88
+ - lib/generators/annotate_rb/config/config_generator.rb
89
+ - lib/generators/annotate_rb/hook/USAGE
90
+ - lib/generators/annotate_rb/hook/hook_generator.rb
91
+ - lib/generators/annotate_rb/hook/templates/annotate_rb.rake
83
92
  - lib/generators/annotate_rb/install/USAGE
84
93
  - lib/generators/annotate_rb/install/install_generator.rb
85
- - lib/generators/annotate_rb/install/templates/annotate_rb.rake
94
+ - lib/generators/annotate_rb/update_config/USAGE
95
+ - lib/generators/annotate_rb/update_config/update_config_generator.rb
86
96
  homepage: https://github.com/drwl/annotaterb
87
97
  licenses:
88
98
  - BSD-2-Clause
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- # Generates the text file content with annotations, these are then to be written to filesystem.
6
- class FileBuilder
7
- def initialize(file_components, annotation_position, options)
8
- @file_components = file_components
9
- @annotation_position = annotation_position
10
- @options = options
11
-
12
- @new_wrapped_annotations = wrapped_content(@file_components.new_annotations)
13
- end
14
-
15
- def generate_content_with_new_annotations
16
- # Need to keep `.to_s` for now since the it can be either a String or Symbol
17
- annotation_write_position = @options[@annotation_position].to_s
18
-
19
- _content = if %w[after bottom].include?(annotation_write_position)
20
- @file_components.magic_comments + (@file_components.pure_file_content.rstrip + "\n\n" + @new_wrapped_annotations)
21
- elsif @file_components.magic_comments.empty?
22
- @file_components.magic_comments + @new_wrapped_annotations + @file_components.pure_file_content.lstrip
23
- else
24
- @file_components.magic_comments + "\n" + @new_wrapped_annotations + @file_components.pure_file_content.lstrip
25
- end
26
- end
27
-
28
- def update_existing_annotations
29
- return "" if !@file_components.has_annotations?
30
-
31
- annotation_pattern = AnnotationPatternGenerator.call(@options)
32
-
33
- new_annotation = @file_components.space_before_annotation + @new_wrapped_annotations + @file_components.space_after_annotation
34
-
35
- _content = @file_components.current_file_content.sub(annotation_pattern, new_annotation)
36
- end
37
-
38
- private
39
-
40
- def wrapped_content(content)
41
- wrapper_open = if @options[:wrapper_open]
42
- "# #{@options[:wrapper_open]}\n"
43
- else
44
- ""
45
- end
46
-
47
- wrapper_close = if @options[:wrapper_close]
48
- "# #{@options[:wrapper_close]}\n"
49
- else
50
- ""
51
- end
52
-
53
- _wrapped_info_block = "#{wrapper_open}#{content}#{wrapper_close}"
54
- end
55
- end
56
- end
57
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- # Extracts magic comments strings and returns them
6
- class MagicCommentParser
7
- MAGIC_COMMENTS = [
8
- HASH_ENCODING = /(^#\s*encoding:.*(?:\n|r\n))/,
9
- HASH_CODING = /(^# coding:.*(?:\n|\r\n))/,
10
- HASH_FROZEN_STRING = /(^#\s*frozen_string_literal:.+(?:\n|\r\n))/,
11
- STAR_ENCODING = /(^# -\*- encoding\s?:.*(?:\n|\r\n))/,
12
- STAR_CODING = /(^# -\*- coding:.*(?:\n|\r\n))/,
13
- STAR_FROZEN_STRING = /(^# -\*- frozen_string_literal\s*:.+-\*-(?:\n|\r\n))/,
14
- SORBET_TYPED_STRING = /(^#\s*typed:.*(?:\n|r\n))/.freeze
15
- ].freeze
16
-
17
- MAGIC_COMMENTS_REGEX = Regexp.union(*MAGIC_COMMENTS).freeze
18
-
19
- class << self
20
- def call(content)
21
- magic_comments = content.scan(MAGIC_COMMENTS_REGEX).flatten.compact
22
-
23
- if magic_comments.any?
24
- magic_comments.join
25
- else
26
- ""
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end