annotaterb 4.1.0 → 4.2.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +68 -0
  3. data/README.md +4 -5
  4. data/VERSION +1 -1
  5. data/exe/annotaterb +7 -7
  6. data/lib/annotate_rb/active_record_patch.rb +2 -0
  7. data/lib/annotate_rb/commands/annotate_models.rb +0 -1
  8. data/lib/annotate_rb/commands/annotate_routes.rb +0 -1
  9. data/lib/annotate_rb/commands/print_help.rb +0 -1
  10. data/lib/annotate_rb/commands/print_version.rb +0 -1
  11. data/lib/annotate_rb/commands.rb +4 -4
  12. data/lib/annotate_rb/config_finder.rb +1 -1
  13. data/lib/annotate_rb/config_loader.rb +2 -2
  14. data/lib/annotate_rb/core.rb +3 -3
  15. data/lib/annotate_rb/helper.rb +16 -0
  16. data/lib/annotate_rb/model_annotator/{annotation_generator.rb → annotation_builder.rb} +18 -14
  17. data/lib/annotate_rb/model_annotator/annotation_decider.rb +10 -12
  18. data/lib/annotate_rb/model_annotator/annotation_diff.rb +19 -0
  19. data/lib/annotate_rb/model_annotator/annotation_diff_generator.rb +44 -0
  20. data/lib/annotate_rb/model_annotator/annotation_pattern_generator.rb +3 -3
  21. data/lib/annotate_rb/model_annotator/annotator.rb +12 -53
  22. data/lib/annotate_rb/model_annotator/column_annotation/annotation_builder.rb +135 -0
  23. data/lib/annotate_rb/model_annotator/column_annotation/attributes_builder.rb +104 -0
  24. data/lib/annotate_rb/model_annotator/column_annotation/column_wrapper.rb +103 -0
  25. data/lib/annotate_rb/model_annotator/column_annotation/type_builder.rb +54 -0
  26. data/lib/annotate_rb/model_annotator/column_annotation.rb +12 -0
  27. data/lib/annotate_rb/model_annotator/file_builder.rb +58 -0
  28. data/lib/annotate_rb/model_annotator/file_components.rb +78 -0
  29. data/lib/annotate_rb/model_annotator/file_name_resolver.rb +3 -3
  30. data/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder.rb +57 -0
  31. data/lib/annotate_rb/model_annotator/foreign_key_annotation.rb +9 -0
  32. data/lib/annotate_rb/model_annotator/index_annotation/annotation_builder.rb +113 -0
  33. data/lib/annotate_rb/model_annotator/index_annotation.rb +9 -0
  34. data/lib/annotate_rb/model_annotator/magic_comment_parser.rb +32 -0
  35. data/lib/annotate_rb/model_annotator/model_class_getter.rb +6 -6
  36. data/lib/annotate_rb/model_annotator/model_files_getter.rb +12 -10
  37. data/lib/annotate_rb/model_annotator/model_wrapper.rb +44 -37
  38. data/lib/annotate_rb/model_annotator/pattern_getter.rb +142 -10
  39. data/lib/annotate_rb/model_annotator/project_annotation_remover.rb +65 -0
  40. data/lib/annotate_rb/model_annotator/project_annotator.rb +63 -0
  41. data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +16 -18
  42. data/lib/annotate_rb/model_annotator/single_file_annotation_remover.rb +37 -0
  43. data/lib/annotate_rb/model_annotator/single_file_annotator.rb +49 -0
  44. data/lib/annotate_rb/model_annotator/{file_annotator_instruction.rb → single_file_annotator_instruction.rb} +2 -2
  45. data/lib/annotate_rb/model_annotator/single_file_remove_annotation_instruction.rb +15 -0
  46. data/lib/annotate_rb/model_annotator.rb +25 -24
  47. data/lib/annotate_rb/options.rb +20 -25
  48. data/lib/annotate_rb/parser.rb +150 -142
  49. data/lib/annotate_rb/rake_bootstrapper.rb +8 -8
  50. data/lib/annotate_rb/route_annotator/annotation_processor.rb +7 -8
  51. data/lib/annotate_rb/route_annotator/annotator.rb +2 -2
  52. data/lib/annotate_rb/route_annotator/base_processor.rb +3 -3
  53. data/lib/annotate_rb/route_annotator/header_generator.rb +15 -15
  54. data/lib/annotate_rb/route_annotator/helper.rb +9 -9
  55. data/lib/annotate_rb/route_annotator/removal_processor.rb +4 -4
  56. data/lib/annotate_rb/route_annotator.rb +6 -6
  57. data/lib/annotate_rb/runner.rb +0 -4
  58. data/lib/annotate_rb/tasks/annotate_models_migrate.rake +5 -5
  59. data/lib/annotate_rb.rb +19 -19
  60. data/lib/generators/annotate_rb/install/install_generator.rb +3 -2
  61. data/lib/generators/annotate_rb/install/templates/annotate_rb.rake +1 -1
  62. metadata +24 -16
  63. data/lib/annotate_rb/model_annotator/column_annotation_builder.rb +0 -92
  64. data/lib/annotate_rb/model_annotator/column_attributes_builder.rb +0 -102
  65. data/lib/annotate_rb/model_annotator/column_type_builder.rb +0 -51
  66. data/lib/annotate_rb/model_annotator/column_wrapper.rb +0 -84
  67. data/lib/annotate_rb/model_annotator/constants.rb +0 -22
  68. data/lib/annotate_rb/model_annotator/file_annotation_remover.rb +0 -25
  69. data/lib/annotate_rb/model_annotator/file_annotator.rb +0 -83
  70. data/lib/annotate_rb/model_annotator/file_patterns.rb +0 -129
  71. data/lib/annotate_rb/model_annotator/foreign_key_annotation_builder.rb +0 -55
  72. data/lib/annotate_rb/model_annotator/helper.rb +0 -107
  73. data/lib/annotate_rb/model_annotator/index_annotation_builder.rb +0 -74
  74. data/lib/annotate_rb/model_annotator/model_file_annotator.rb +0 -55
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module IndexAnnotation
6
+ class AnnotationBuilder
7
+ INDEX_CLAUSES = {
8
+ unique: {
9
+ default: "UNIQUE",
10
+ markdown: "_unique_"
11
+ },
12
+ where: {
13
+ default: "WHERE",
14
+ markdown: "_where_"
15
+ },
16
+ using: {
17
+ default: "USING",
18
+ markdown: "_using_"
19
+ }
20
+ }.freeze
21
+
22
+ def initialize(model, options)
23
+ @model = model
24
+ @options = options
25
+ end
26
+
27
+ def build
28
+ index_info = if @options[:format_markdown]
29
+ "#\n# ### Indexes\n#\n"
30
+ else
31
+ "#\n# Indexes\n#\n"
32
+ end
33
+
34
+ indexes = @model.retrieve_indexes_from_table
35
+ return "" if indexes.empty?
36
+
37
+ max_size = indexes.collect { |index| index.name.size }.max + 1
38
+ indexes.sort_by(&:name).each do |index|
39
+ index_info += if @options[:format_markdown]
40
+ final_index_string_in_markdown(index)
41
+ else
42
+ final_index_string(index, max_size)
43
+ end
44
+ end
45
+
46
+ index_info
47
+ end
48
+
49
+ private
50
+
51
+ def index_using_info(index, format = :default)
52
+ value = index.try(:using) && index.using.try(:to_sym)
53
+ if !value.blank? && value != :btree
54
+ " #{INDEX_CLAUSES[:using][format]} #{value}"
55
+ else
56
+ ""
57
+ end
58
+ end
59
+
60
+ def index_where_info(index, format = :default)
61
+ value = index.try(:where).try(:to_s)
62
+ if value.blank?
63
+ ""
64
+ else
65
+ " #{INDEX_CLAUSES[:where][format]} #{value}"
66
+ end
67
+ end
68
+
69
+ def index_unique_info(index, format = :default)
70
+ index.unique ? " #{INDEX_CLAUSES[:unique][format]}" : ""
71
+ end
72
+
73
+ def final_index_string_in_markdown(index)
74
+ details = format(
75
+ "%s%s%s",
76
+ index_unique_info(index, :markdown),
77
+ index_where_info(index, :markdown),
78
+ index_using_info(index, :markdown)
79
+ ).strip
80
+ details = " (#{details})" unless details.blank?
81
+
82
+ format(
83
+ "# * `%s`%s:\n# * **`%s`**\n",
84
+ index.name,
85
+ details,
86
+ index_columns_info(index).join("`**\n# * **`")
87
+ )
88
+ end
89
+
90
+ def final_index_string(index, max_size)
91
+ format(
92
+ "# %-#{max_size}.#{max_size}s %s%s%s%s",
93
+ index.name,
94
+ "(#{index_columns_info(index).join(",")})",
95
+ index_unique_info(index),
96
+ index_where_info(index),
97
+ index_using_info(index)
98
+ ).rstrip + "\n"
99
+ end
100
+
101
+ def index_columns_info(index)
102
+ Array(index.columns).map do |col|
103
+ if index.try(:orders) && index.orders[col.to_s]
104
+ "#{col} #{index.orders[col.to_s].upcase}"
105
+ else
106
+ col.to_s.gsub("\r", '\r').gsub("\n", '\n')
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module IndexAnnotation
6
+ autoload :AnnotationBuilder, "annotate_rb/model_annotator/index_annotation/annotation_builder"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
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
@@ -8,8 +8,8 @@ module AnnotateRb
8
8
  # Check for namespaced models in subdirectories as well as models
9
9
  # in subdirectories without namespacing.
10
10
  def call(file, options)
11
- model_path = file.gsub(/\.rb$/, '')
12
- options[:model_dir].each { |dir| model_path = model_path.gsub(/^#{dir}/, '').gsub(/^\//, '') }
11
+ model_path = file.gsub(/\.rb$/, "")
12
+ options[:model_dir].each { |dir| model_path = model_path.gsub(/^#{dir}/, "").gsub(/^\//, "") }
13
13
 
14
14
  begin
15
15
  get_loaded_model(model_path, file) || raise(BadModelFileError.new)
@@ -18,8 +18,8 @@ module AnnotateRb
18
18
  file_path = File.expand_path(file)
19
19
  if File.file?(file_path) && Kernel.require(file_path)
20
20
  retry
21
- elsif model_path =~ /\//
22
- model_path = model_path.split('/')[1..-1].join('/').to_s
21
+ elsif /\//.match?(model_path)
22
+ model_path = model_path.split("/")[1..-1].join("/").to_s
23
23
  retry
24
24
  else
25
25
  raise
@@ -39,7 +39,7 @@ module AnnotateRb
39
39
  absolute_file = File.expand_path(file)
40
40
  model_paths =
41
41
  $LOAD_PATH.select { |path| absolute_file.include?(path) }
42
- .map { |path| absolute_file.sub(path, '').sub(/\.rb$/, '').sub(/^\//, '') }
42
+ .map { |path| absolute_file.sub(path, "").sub(/\.rb$/, "").sub(/^\//, "") }
43
43
  model_paths
44
44
  .map { |path| get_loaded_model_by_path(path) }
45
45
  .find { |loaded_model| !loaded_model.nil? }
@@ -51,7 +51,7 @@ module AnnotateRb
51
51
  rescue StandardError, LoadError
52
52
  # Revert to the old way but it is not really robust
53
53
  ObjectSpace.each_object(::Class)
54
- .select do |c|
54
+ .select do |c|
55
55
  Class === c && # note: we use === to avoid a bug in activesupport 2.3.14 OptionMerger vs. is_a?
56
56
  c.ancestors.respond_to?(:include?) && # to fix FactoryGirl bug, see https://github.com/ctran/annotate_models/pull/82
57
57
  c.ancestors.include?(::ActiveRecord::Base)
@@ -20,19 +20,21 @@ module AnnotateRb
20
20
  options[:model_dir].each do |dir|
21
21
  Dir.chdir(dir) do
22
22
  list = if options[:ignore_model_sub_dir]
23
- Dir["*.rb"].map { |f| [dir, f] }
24
- else
25
- Dir["**/*.rb"].reject { |f| f["concerns/"] }.map { |f| [dir, f] }
26
- end
23
+ Dir["*.rb"].map { |f| [dir, f] }
24
+ else
25
+ Dir["**/*.rb"]
26
+ .reject { |f| f["concerns/"] }
27
+ .map { |f| [dir, f] }
28
+ end
27
29
  model_files.concat(list)
28
30
  end
29
31
  end
30
32
 
31
33
  model_files
32
34
  rescue SystemCallError
33
- $stderr.puts "No models found in directory '#{options[:model_dir].join("', '")}'."
34
- $stderr.puts "Either specify models on the command line, or use the --model-dir option."
35
- $stderr.puts "Call 'annotaterb --help' for more info."
35
+ warn "No models found in directory '#{options[:model_dir].join("', '")}'."
36
+ warn "Either specify models on the command line, or use the --model-dir option."
37
+ warn "Call 'annotaterb --help' for more info."
36
38
  # exit 1 # TODO: Return exit code back to caller. Right now it messes up RSpec being able to run
37
39
  end
38
40
 
@@ -47,12 +49,12 @@ module AnnotateRb
47
49
  absolute_dir_path = File.expand_path(dir)
48
50
  specified_files
49
51
  .find_all { |file| file.start_with?(absolute_dir_path) }
50
- .map { |file| [dir, file.sub("#{absolute_dir_path}/", '')] }
52
+ .map { |file| [dir, file.sub("#{absolute_dir_path}/", "")] }
51
53
  end
52
54
 
53
55
  if model_files.size != specified_files.size
54
- $stderr.puts "The specified file could not be found in directory '#{options[:model_dir].join("', '")}'."
55
- $stderr.puts "Call 'annotaterb --help' for more info."
56
+ warn "The specified file could not be found in directory '#{options[:model_dir].join("', '")}'."
57
+ warn "Call 'annotaterb --help' for more info."
56
58
  # exit 1 # TODO: Return exit code back to caller. Right now it messes up RSpec being able to run
57
59
  end
58
60
 
@@ -13,22 +13,23 @@ module AnnotateRb
13
13
 
14
14
  # Gets the columns of the ActiveRecord model, processes them, and then returns them.
15
15
  def columns
16
- @columns ||= begin
17
- cols = raw_columns
18
- cols += translated_columns
19
-
20
- ignore_columns = @options[:ignore_columns]
21
- if ignore_columns
22
- cols = cols.reject do |col|
23
- col.name.match(/#{ignore_columns}/)
24
- end
25
- end
26
-
27
- cols = cols.sort_by(&:name) if @options[:sort]
28
- cols = classified_sort(cols) if @options[:classified_sort]
29
-
30
- cols
31
- end
16
+ @columns ||=
17
+ begin
18
+ cols = raw_columns
19
+ cols += translated_columns
20
+
21
+ ignore_columns = @options[:ignore_columns]
22
+ if ignore_columns
23
+ cols = cols.reject do |col|
24
+ col.name.match(/#{ignore_columns}/)
25
+ end
26
+ end
27
+
28
+ cols = cols.sort_by(&:name) if @options[:sort]
29
+ cols = classified_sort(cols) if @options[:classified_sort]
30
+
31
+ cols
32
+ end
32
33
  end
33
34
 
34
35
  def connection
@@ -75,19 +76,25 @@ module AnnotateRb
75
76
  # Calculates the max width of the schema for the model by looking at the columns, schema comments, with respect
76
77
  # to the options.
77
78
  def max_schema_info_width
78
- cols = columns
79
-
80
- if with_comments?
81
- max_size = cols.map do |column|
82
- column.name.size + (column.comment ? Helper.width(column.comment) : 0)
83
- end.max || 0
84
- max_size += 2
85
- else
86
- max_size = cols.map(&:name).map(&:size).max
87
- end
88
- max_size += @options[:format_rdoc] ? 5 : 1
79
+ @max_schema_info_width ||=
80
+ begin
81
+ cols = columns
82
+
83
+ if with_comments?
84
+ column_widths = cols.map do |column|
85
+ column.name.size + (column.comment ? Helper.width(column.comment) : 0)
86
+ end
89
87
 
90
- max_size
88
+ max_size = column_widths.max || 0
89
+ max_size += 2
90
+ else
91
+ max_size = cols.map(&:name).map(&:size).max
92
+ end
93
+
94
+ max_size += @options[:format_rdoc] ? 5 : 1
95
+
96
+ max_size
97
+ end
91
98
  end
92
99
 
93
100
  def retrieve_indexes_from_table
@@ -98,12 +105,12 @@ module AnnotateRb
98
105
  return indexes if indexes.any? || !@klass.table_name_prefix
99
106
 
100
107
  # Try to search the table without prefix
101
- table_name_without_prefix = table_name.to_s.sub(@klass.table_name_prefix, '')
108
+ table_name_without_prefix = table_name.to_s.sub(@klass.table_name_prefix, "")
102
109
  @klass.connection.indexes(table_name_without_prefix)
103
110
  end
104
111
 
105
112
  def with_comments?
106
- @options[:with_comment] &&
113
+ @with_comments ||= @options[:with_comment] &&
107
114
  raw_columns.first.respond_to?(:comment) &&
108
115
  raw_columns.map(&:comment).any? { |comment| !comment.nil? }
109
116
  end
@@ -115,11 +122,11 @@ module AnnotateRb
115
122
  id = nil
116
123
 
117
124
  cols.each do |c|
118
- if c.name.eql?('id')
125
+ if c.name.eql?("id")
119
126
  id = c
120
- elsif c.name.eql?('created_at') || c.name.eql?('updated_at')
127
+ elsif c.name.eql?("created_at") || c.name.eql?("updated_at")
121
128
  timestamps << c
122
- elsif c.name[-3, 3].eql?('_id')
129
+ elsif c.name[-3, 3].eql?("_id")
123
130
  associations << c
124
131
  else
125
132
  rest_cols << c
@@ -137,9 +144,9 @@ module AnnotateRb
137
144
  # eg. Model: Car, foreign column name: car_id
138
145
  foreign_column_name = [
139
146
  @klass.translation_class.to_s
140
- .gsub('::Translation', '').gsub('::', '_')
141
- .downcase,
142
- '_id'
147
+ .gsub("::Translation", "").gsub("::", "_")
148
+ .downcase,
149
+ "_id"
143
150
  ].join.to_sym
144
151
 
145
152
  [
@@ -152,4 +159,4 @@ module AnnotateRb
152
159
  end
153
160
  end
154
161
  end
155
- end
162
+ end
@@ -3,25 +3,157 @@
3
3
  module AnnotateRb
4
4
  module ModelAnnotator
5
5
  class PatternGetter
6
+ module FilePatterns
7
+ # Controller files
8
+ CONTROLLER_DIR = File.join("app", "controllers")
9
+
10
+ # Active admin registry files
11
+ ACTIVEADMIN_DIR = File.join("app", "admin")
12
+
13
+ # Helper files
14
+ HELPER_DIR = File.join("app", "helpers")
15
+
16
+ # File.join for windows reverse bar compat?
17
+ # I dont use windows, can`t test
18
+ UNIT_TEST_DIR = File.join("test", "unit")
19
+ MODEL_TEST_DIR = File.join("test", "models") # since rails 4.0
20
+ SPEC_MODEL_DIR = File.join("spec", "models")
21
+
22
+ FIXTURE_TEST_DIR = File.join("test", "fixtures")
23
+ FIXTURE_SPEC_DIR = File.join("spec", "fixtures")
24
+
25
+ # Other test files
26
+ CONTROLLER_TEST_DIR = File.join("test", "controllers")
27
+ CONTROLLER_SPEC_DIR = File.join("spec", "controllers")
28
+ REQUEST_SPEC_DIR = File.join("spec", "requests")
29
+ ROUTING_SPEC_DIR = File.join("spec", "routing")
30
+
31
+ # Object Daddy http://github.com/flogic/object_daddy/tree/master
32
+ EXEMPLARS_TEST_DIR = File.join("test", "exemplars")
33
+ EXEMPLARS_SPEC_DIR = File.join("spec", "exemplars")
34
+
35
+ # Machinist http://github.com/notahat/machinist
36
+ BLUEPRINTS_TEST_DIR = File.join("test", "blueprints")
37
+ BLUEPRINTS_SPEC_DIR = File.join("spec", "blueprints")
38
+
39
+ # Factory Bot https://github.com/thoughtbot/factory_bot
40
+ FACTORY_BOT_TEST_DIR = File.join("test", "factories")
41
+ FACTORY_BOT_SPEC_DIR = File.join("spec", "factories")
42
+
43
+ # Fabrication https://github.com/paulelliott/fabrication.git
44
+ FABRICATORS_TEST_DIR = File.join("test", "fabricators")
45
+ FABRICATORS_SPEC_DIR = File.join("spec", "fabricators")
46
+
47
+ # Serializers https://github.com/rails-api/active_model_serializers
48
+ SERIALIZERS_DIR = File.join("app", "serializers")
49
+ SERIALIZERS_TEST_DIR = File.join("test", "serializers")
50
+ SERIALIZERS_SPEC_DIR = File.join("spec", "serializers")
51
+ end
52
+
6
53
  class << self
7
54
  def call(options, pattern_types = [])
8
- current_patterns = []
55
+ new(options, pattern_types).get
56
+ end
57
+ end
58
+
59
+ def initialize(options, pattern_types = [])
60
+ @options = options
61
+ @pattern_types = pattern_types
62
+ end
9
63
 
10
- options[:root_dir].each do |root_directory|
11
- Array(pattern_types).each do |pattern_type|
12
- patterns = FilePatterns.generate(root_directory, pattern_type, options)
64
+ def get
65
+ current_patterns = []
13
66
 
14
- current_patterns += if pattern_type.to_sym == :additional_file_patterns
15
- patterns
16
- else
17
- patterns.map { |p| p.sub(/^[\/]*/, '') }
18
- end
67
+ @options[:root_dir].each do |root_directory|
68
+ Array(@pattern_types).each do |pattern_type|
69
+ patterns = generate(root_directory, pattern_type)
70
+
71
+ current_patterns += if pattern_type.to_sym == :additional_file_patterns
72
+ patterns
73
+ else
74
+ patterns.map { |p| p.sub(/^\/*/, "") }
19
75
  end
20
76
  end
77
+ end
78
+
79
+ current_patterns
80
+ end
21
81
 
22
- current_patterns
82
+ private
83
+
84
+ def generate(root_directory, pattern_type)
85
+ case pattern_type
86
+ when "test" then test_files(root_directory)
87
+ when "fixture" then fixture_files(root_directory)
88
+ when "scaffold" then scaffold_files(root_directory)
89
+ when "factory" then factory_files(root_directory)
90
+ when "serializer" then serialize_files(root_directory)
91
+ when "additional_file_patterns"
92
+ [@options[:additional_file_patterns] || []].flatten
93
+ when "controller"
94
+ [File.join(root_directory, FilePatterns::CONTROLLER_DIR, "%PLURALIZED_MODEL_NAME%_controller.rb")]
95
+ when "admin"
96
+ [
97
+ File.join(root_directory, FilePatterns::ACTIVEADMIN_DIR, "%MODEL_NAME%.rb"),
98
+ File.join(root_directory, FilePatterns::ACTIVEADMIN_DIR, "%PLURALIZED_MODEL_NAME%.rb")
99
+ ]
100
+ when "helper"
101
+ [File.join(root_directory, FilePatterns::HELPER_DIR, "%PLURALIZED_MODEL_NAME%_helper.rb")]
102
+ else
103
+ []
23
104
  end
24
105
  end
106
+
107
+ def test_files(root_directory)
108
+ [
109
+ File.join(root_directory, FilePatterns::UNIT_TEST_DIR, "%MODEL_NAME%_test.rb"),
110
+ File.join(root_directory, FilePatterns::MODEL_TEST_DIR, "%MODEL_NAME%_test.rb"),
111
+ File.join(root_directory, FilePatterns::SPEC_MODEL_DIR, "%MODEL_NAME%_spec.rb")
112
+ ]
113
+ end
114
+
115
+ def fixture_files(root_directory)
116
+ [
117
+ File.join(root_directory, FilePatterns::FIXTURE_TEST_DIR, "%TABLE_NAME%.yml"),
118
+ File.join(root_directory, FilePatterns::FIXTURE_SPEC_DIR, "%TABLE_NAME%.yml"),
119
+ File.join(root_directory, FilePatterns::FIXTURE_TEST_DIR, "%PLURALIZED_MODEL_NAME%.yml"),
120
+ File.join(root_directory, FilePatterns::FIXTURE_SPEC_DIR, "%PLURALIZED_MODEL_NAME%.yml")
121
+ ]
122
+ end
123
+
124
+ def scaffold_files(root_directory)
125
+ [
126
+ File.join(root_directory, FilePatterns::CONTROLLER_TEST_DIR, "%PLURALIZED_MODEL_NAME%_controller_test.rb"),
127
+ File.join(root_directory, FilePatterns::CONTROLLER_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_controller_spec.rb"),
128
+ File.join(root_directory, FilePatterns::REQUEST_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_spec.rb"),
129
+ File.join(root_directory, FilePatterns::ROUTING_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_routing_spec.rb")
130
+ ]
131
+ end
132
+
133
+ def factory_files(root_directory)
134
+ [
135
+ File.join(root_directory, FilePatterns::EXEMPLARS_TEST_DIR, "%MODEL_NAME%_exemplar.rb"),
136
+ File.join(root_directory, FilePatterns::EXEMPLARS_SPEC_DIR, "%MODEL_NAME%_exemplar.rb"),
137
+ File.join(root_directory, FilePatterns::BLUEPRINTS_TEST_DIR, "%MODEL_NAME%_blueprint.rb"),
138
+ File.join(root_directory, FilePatterns::BLUEPRINTS_SPEC_DIR, "%MODEL_NAME%_blueprint.rb"),
139
+ File.join(root_directory, FilePatterns::FACTORY_BOT_TEST_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
140
+ File.join(root_directory, FilePatterns::FACTORY_BOT_SPEC_DIR, "%MODEL_NAME%_factory.rb"), # (old style)
141
+ File.join(root_directory, FilePatterns::FACTORY_BOT_TEST_DIR, "%TABLE_NAME%.rb"), # (new style)
142
+ File.join(root_directory, FilePatterns::FACTORY_BOT_SPEC_DIR, "%TABLE_NAME%.rb"), # (new style)
143
+ File.join(root_directory, FilePatterns::FACTORY_BOT_TEST_DIR, "%PLURALIZED_MODEL_NAME%.rb"), # (new style)
144
+ File.join(root_directory, FilePatterns::FACTORY_BOT_SPEC_DIR, "%PLURALIZED_MODEL_NAME%.rb"), # (new style)
145
+ File.join(root_directory, FilePatterns::FABRICATORS_TEST_DIR, "%MODEL_NAME%_fabricator.rb"),
146
+ File.join(root_directory, FilePatterns::FABRICATORS_SPEC_DIR, "%MODEL_NAME%_fabricator.rb")
147
+ ]
148
+ end
149
+
150
+ def serialize_files(root_directory)
151
+ [
152
+ File.join(root_directory, FilePatterns::SERIALIZERS_DIR, "%MODEL_NAME%_serializer.rb"),
153
+ File.join(root_directory, FilePatterns::SERIALIZERS_TEST_DIR, "%MODEL_NAME%_serializer_test.rb"),
154
+ File.join(root_directory, FilePatterns::SERIALIZERS_SPEC_DIR, "%MODEL_NAME%_serializer_spec.rb")
155
+ ]
156
+ end
25
157
  end
26
158
  end
27
159
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ class ProjectAnnotationRemover
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def remove_annotations
11
+ project_model_files = model_files
12
+
13
+ removal_instructions = project_model_files.map do |path, filename|
14
+ file = File.join(path, filename)
15
+
16
+ if AnnotationDecider.new(file, @options).annotate?
17
+ _instructions = build_instructions_for_file(file)
18
+ end
19
+ end.flatten.compact
20
+
21
+ deannotated = removal_instructions.map do |instruction|
22
+ if SingleFileAnnotationRemover.call_with_instructions(instruction)
23
+ instruction.file
24
+ end
25
+ rescue => e
26
+ warn "Unable to process #{File.join(instruction.file)}: #{e.message}"
27
+ warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
28
+ end.flatten.compact
29
+
30
+ if deannotated.empty?
31
+ puts "Model files unchanged."
32
+ else
33
+ puts "Removed annotations (#{deannotated.length}) from: #{deannotated.join(", ")}"
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def build_instructions_for_file(file)
40
+ klass = ModelClassGetter.call(file, @options)
41
+
42
+ instructions = []
43
+
44
+ klass.reset_column_information
45
+ model_name = klass.name.underscore
46
+ table_name = klass.table_name
47
+
48
+ model_instruction = SingleFileRemoveAnnotationInstruction.new(file, @options)
49
+ instructions << model_instruction
50
+
51
+ related_files = RelatedFilesListBuilder.new(file, model_name, table_name, @options).build
52
+ related_file_instructions = related_files.map do |f, _position_key|
53
+ _instruction = SingleFileRemoveAnnotationInstruction.new(f, @options)
54
+ end
55
+ instructions.concat(related_file_instructions)
56
+
57
+ instructions
58
+ end
59
+
60
+ def model_files
61
+ @model_files ||= ModelFilesGetter.call(@options)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ class ProjectAnnotator
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def annotate
11
+ project_model_files = model_files
12
+
13
+ annotation_instructions = project_model_files.map do |path, filename|
14
+ file = File.join(path, filename)
15
+
16
+ if AnnotationDecider.new(file, @options).annotate?
17
+ _instructions = build_instructions_for_file(file)
18
+ end
19
+ end.flatten.compact
20
+
21
+ annotated = annotation_instructions.map do |instruction|
22
+ if SingleFileAnnotator.call_with_instructions(instruction)
23
+ instruction.file
24
+ end
25
+ end.compact
26
+
27
+ if annotated.empty?
28
+ puts "Model files unchanged."
29
+ else
30
+ puts "Annotated (#{annotated.length}): #{annotated.join(", ")}"
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def build_instructions_for_file(file)
37
+ klass = ModelClassGetter.call(file, @options)
38
+
39
+ instructions = []
40
+
41
+ klass.reset_column_information
42
+ annotation = AnnotationBuilder.new(klass, @options).build
43
+ model_name = klass.name.underscore
44
+ table_name = klass.table_name
45
+
46
+ model_instruction = SingleFileAnnotatorInstruction.new(file, annotation, :position_in_class, @options)
47
+ instructions << model_instruction
48
+
49
+ related_files = RelatedFilesListBuilder.new(file, model_name, table_name, @options).build
50
+ related_file_instructions = related_files.map do |f, position_key|
51
+ _instruction = SingleFileAnnotatorInstruction.new(f, annotation, position_key, @options)
52
+ end
53
+ instructions.concat(related_file_instructions)
54
+
55
+ instructions
56
+ end
57
+
58
+ def model_files
59
+ @model_files ||= ModelFilesGetter.call(@options)
60
+ end
61
+ end
62
+ end
63
+ end