annotaterb 4.1.0 → 4.2.0

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