annotaterb 4.4.1 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
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