annotaterb 4.1.1 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +68 -0
  3. data/VERSION +1 -1
  4. data/exe/annotaterb +7 -7
  5. data/lib/annotate_rb/active_record_patch.rb +2 -0
  6. data/lib/annotate_rb/commands/annotate_models.rb +0 -1
  7. data/lib/annotate_rb/commands/annotate_routes.rb +0 -1
  8. data/lib/annotate_rb/commands/print_help.rb +0 -1
  9. data/lib/annotate_rb/commands/print_version.rb +0 -1
  10. data/lib/annotate_rb/commands.rb +4 -4
  11. data/lib/annotate_rb/config_finder.rb +1 -1
  12. data/lib/annotate_rb/config_loader.rb +2 -2
  13. data/lib/annotate_rb/core.rb +3 -3
  14. data/lib/annotate_rb/helper.rb +16 -0
  15. data/lib/annotate_rb/model_annotator/{annotation_generator.rb → annotation_builder.rb} +18 -14
  16. data/lib/annotate_rb/model_annotator/annotation_decider.rb +10 -12
  17. data/lib/annotate_rb/model_annotator/annotation_diff.rb +1 -1
  18. data/lib/annotate_rb/model_annotator/annotation_diff_generator.rb +9 -9
  19. data/lib/annotate_rb/model_annotator/annotation_pattern_generator.rb +3 -3
  20. data/lib/annotate_rb/model_annotator/annotator.rb +12 -53
  21. data/lib/annotate_rb/model_annotator/column_annotation/annotation_builder.rb +135 -0
  22. data/lib/annotate_rb/model_annotator/column_annotation/attributes_builder.rb +104 -0
  23. data/lib/annotate_rb/model_annotator/column_annotation/column_wrapper.rb +103 -0
  24. data/lib/annotate_rb/model_annotator/column_annotation/type_builder.rb +54 -0
  25. data/lib/annotate_rb/model_annotator/column_annotation.rb +12 -0
  26. data/lib/annotate_rb/model_annotator/file_builder.rb +58 -0
  27. data/lib/annotate_rb/model_annotator/file_components.rb +78 -0
  28. data/lib/annotate_rb/model_annotator/file_name_resolver.rb +3 -3
  29. data/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder.rb +57 -0
  30. data/lib/annotate_rb/model_annotator/foreign_key_annotation.rb +9 -0
  31. data/lib/annotate_rb/model_annotator/index_annotation/annotation_builder.rb +113 -0
  32. data/lib/annotate_rb/model_annotator/index_annotation.rb +9 -0
  33. data/lib/annotate_rb/model_annotator/magic_comment_parser.rb +32 -0
  34. data/lib/annotate_rb/model_annotator/model_class_getter.rb +6 -6
  35. data/lib/annotate_rb/model_annotator/model_files_getter.rb +12 -10
  36. data/lib/annotate_rb/model_annotator/model_wrapper.rb +44 -37
  37. data/lib/annotate_rb/model_annotator/pattern_getter.rb +142 -10
  38. data/lib/annotate_rb/model_annotator/project_annotation_remover.rb +65 -0
  39. data/lib/annotate_rb/model_annotator/project_annotator.rb +63 -0
  40. data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +16 -18
  41. data/lib/annotate_rb/model_annotator/single_file_annotation_remover.rb +37 -0
  42. data/lib/annotate_rb/model_annotator/single_file_annotator.rb +49 -0
  43. data/lib/annotate_rb/model_annotator/{file_annotator_instruction.rb → single_file_annotator_instruction.rb} +2 -2
  44. data/lib/annotate_rb/model_annotator/single_file_remove_annotation_instruction.rb +15 -0
  45. data/lib/annotate_rb/model_annotator.rb +25 -26
  46. data/lib/annotate_rb/options.rb +20 -25
  47. data/lib/annotate_rb/parser.rb +150 -142
  48. data/lib/annotate_rb/rake_bootstrapper.rb +8 -8
  49. data/lib/annotate_rb/route_annotator/annotation_processor.rb +7 -8
  50. data/lib/annotate_rb/route_annotator/annotator.rb +2 -2
  51. data/lib/annotate_rb/route_annotator/base_processor.rb +3 -3
  52. data/lib/annotate_rb/route_annotator/header_generator.rb +15 -15
  53. data/lib/annotate_rb/route_annotator/helper.rb +9 -9
  54. data/lib/annotate_rb/route_annotator/removal_processor.rb +4 -4
  55. data/lib/annotate_rb/route_annotator.rb +6 -6
  56. data/lib/annotate_rb/runner.rb +0 -4
  57. data/lib/annotate_rb/tasks/annotate_models_migrate.rake +5 -5
  58. data/lib/annotate_rb.rb +19 -19
  59. data/lib/generators/annotate_rb/install/install_generator.rb +3 -2
  60. data/lib/generators/annotate_rb/install/templates/annotate_rb.rake +1 -1
  61. metadata +22 -16
  62. data/lib/annotate_rb/model_annotator/column_annotation_builder.rb +0 -92
  63. data/lib/annotate_rb/model_annotator/column_attributes_builder.rb +0 -102
  64. data/lib/annotate_rb/model_annotator/column_type_builder.rb +0 -51
  65. data/lib/annotate_rb/model_annotator/column_wrapper.rb +0 -84
  66. data/lib/annotate_rb/model_annotator/constants.rb +0 -22
  67. data/lib/annotate_rb/model_annotator/file_annotation_remover.rb +0 -25
  68. data/lib/annotate_rb/model_annotator/file_annotator.rb +0 -77
  69. data/lib/annotate_rb/model_annotator/file_patterns.rb +0 -129
  70. data/lib/annotate_rb/model_annotator/foreign_key_annotation_builder.rb +0 -55
  71. data/lib/annotate_rb/model_annotator/helper.rb +0 -107
  72. data/lib/annotate_rb/model_annotator/index_annotation_builder.rb +0 -74
  73. data/lib/annotate_rb/model_annotator/model_file_annotator.rb +0 -55
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- class ColumnWrapper
6
- def initialize(column)
7
- @column = column
8
- end
9
-
10
- def default
11
- # Note: Used to be klass.column_defaults[name], where name is the column name.
12
- # Looks to be identical, but keeping note here in case there are differences.
13
- _column_default = @column.default
14
- end
15
-
16
- def default_string
17
- Helper.quote(@column.default)
18
- end
19
-
20
- def type
21
- @column.type
22
- end
23
-
24
- def column_type_string
25
- if (@column.respond_to?(:bigint?) && @column.bigint?) || /\Abigint\b/ =~ @column.sql_type
26
- 'bigint'
27
- else
28
- (@column.type || @column.sql_type).to_s
29
- end
30
- end
31
-
32
- def unsigned?
33
- @column.respond_to?(:unsigned?) && @column.unsigned?
34
- end
35
-
36
- def null
37
- @column.null
38
- end
39
-
40
- def precision
41
- @column.precision
42
- end
43
-
44
- def scale
45
- @column.scale
46
- end
47
-
48
- def limit
49
- @column.limit
50
- end
51
-
52
- def geometry_type?
53
- @column.respond_to?(:geometry_type)
54
- end
55
-
56
- def geometry_type
57
- # TODO: Check if we need to check if it responds before accessing the geometry type
58
- @column.geometry_type
59
- end
60
-
61
- def geometric_type?
62
- @column.respond_to?(:geometric_type)
63
- end
64
-
65
- def geometric_type
66
- # TODO: Check if we need to check if it responds before accessing the geometric type
67
- @column.geometric_type
68
- end
69
-
70
- def srid
71
- # TODO: Check if we need to check if it responds before accessing the srid
72
- @column.srid
73
- end
74
-
75
- def array?
76
- @column.respond_to?(:array) && @column.array
77
- end
78
-
79
- def name
80
- @column.name
81
- end
82
- end
83
- end
84
- end
@@ -1,22 +0,0 @@
1
- module AnnotateRb
2
- module ModelAnnotator
3
- module Constants
4
- ##
5
- # The set of available options to customize the behavior of Annotate.
6
- #
7
- POSITION_OPTIONS = ::AnnotateRb::Options::POSITION_OPTION_KEYS
8
-
9
- FLAG_OPTIONS = ::AnnotateRb::Options::FLAG_OPTION_KEYS
10
-
11
- OTHER_OPTIONS = ::AnnotateRb::Options::OTHER_OPTION_KEYS
12
-
13
- PATH_OPTIONS = ::AnnotateRb::Options::PATH_OPTION_KEYS
14
-
15
- ALL_ANNOTATE_OPTIONS = ::AnnotateRb::Options::ALL_OPTION_KEYS
16
-
17
- SKIP_ANNOTATION_PREFIX = '# -\*- SkipSchemaAnnotations'.freeze
18
-
19
- MAGIC_COMMENT_MATCHER = Regexp.new(/(^#\s*encoding:.*(?:\n|r\n))|(^# coding:.*(?:\n|\r\n))|(^# -\*- coding:.*(?:\n|\r\n))|(^# -\*- encoding\s?:.*(?:\n|\r\n))|(^#\s*frozen_string_literal:.+(?:\n|\r\n))|(^# -\*- frozen_string_literal\s*:.+-\*-(?:\n|\r\n))/).freeze
20
- end
21
- end
22
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- class FileAnnotationRemover
6
- class << self
7
- def call(file_name, options = Options.from({}))
8
- if File.exist?(file_name)
9
- content = File.read(file_name)
10
- return false if content =~ /#{Constants::SKIP_ANNOTATION_PREFIX}.*\n/
11
-
12
- wrapper_open = options[:wrapper_open] ? "# #{options[:wrapper_open]}\n" : ''
13
- content.sub!(/(#{wrapper_open})?#{AnnotationPatternGenerator.call(options)}/, '')
14
-
15
- File.open(file_name, 'wb') { |f| f.puts content }
16
-
17
- true
18
- else
19
- false
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- class FileAnnotator
6
- class << self
7
- def call_with_instructions(instruction)
8
- call(instruction.file, instruction.annotation, instruction.position, instruction.options)
9
- end
10
-
11
- # Add a schema block to a file. If the file already contains
12
- # a schema info block (a comment starting with "== Schema Information"),
13
- # check if it matches the block that is already there. If so, leave it be.
14
- # If not, remove the old info block and write a new one.
15
- #
16
- # == Returns:
17
- # true or false depending on whether the file was modified.
18
- #
19
- # === Options (opts)
20
- # :force<Symbol>:: whether to update the file even if it doesn't seem to need it.
21
- # :position_in_*<Symbol>:: where to place the annotated section in fixture or model file,
22
- # :before, :top, :after or :bottom. Default is :before.
23
- #
24
- def call(file_name, info_block, position, options = {})
25
- return false unless File.exist?(file_name)
26
- old_content = File.read(file_name)
27
-
28
- return false if old_content =~ /#{Constants::SKIP_ANNOTATION_PREFIX}.*\n/
29
-
30
- diff = AnnotationDiffGenerator.new(old_content, info_block).generate
31
-
32
- return false if !diff.changed? && !options[:force]
33
-
34
- abort "AnnotateRb error. #{file_name} needs to be updated, but annotaterb was run with `--frozen`." if options[:frozen]
35
-
36
- # Replace inline the old schema info with the new schema info
37
- wrapper_open = options[:wrapper_open] ? "# #{options[:wrapper_open]}\n" : ""
38
- wrapper_close = options[:wrapper_close] ? "# #{options[:wrapper_close]}\n" : ""
39
- wrapped_info_block = "#{wrapper_open}#{info_block}#{wrapper_close}"
40
-
41
- annotation_pattern = AnnotationPatternGenerator.call(options)
42
- old_annotation = old_content.match(annotation_pattern).to_s
43
-
44
- # if there *was* no old schema info or :force was passed, we simply
45
- # need to insert it in correct position
46
- if old_annotation.empty? || options[:force]
47
- magic_comments_block = Helper.magic_comments_as_string(old_content)
48
- old_content.gsub!(Constants::MAGIC_COMMENT_MATCHER, '')
49
-
50
- annotation_pattern = AnnotationPatternGenerator.call(options)
51
- old_content.sub!(annotation_pattern, '')
52
-
53
- new_content = if %w(after bottom).include?(options[position].to_s)
54
- magic_comments_block + (old_content.rstrip + "\n\n" + wrapped_info_block)
55
- elsif magic_comments_block.empty?
56
- magic_comments_block + wrapped_info_block + old_content.lstrip
57
- else
58
- magic_comments_block + "\n" + wrapped_info_block + old_content.lstrip
59
- end
60
- else
61
- # replace the old annotation with the new one
62
-
63
- # keep the surrounding whitespace the same
64
- space_match = old_annotation.match(/\A(?<start>\s*).*?\n(?<end>\s*)\z/m)
65
- new_annotation = space_match[:start] + wrapped_info_block + space_match[:end]
66
-
67
- annotation_pattern = AnnotationPatternGenerator.call(options)
68
- new_content = old_content.sub(annotation_pattern, new_annotation)
69
- end
70
-
71
- File.open(file_name, 'wb') { |f| f.puts new_content }
72
- true
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,129 +0,0 @@
1
- module AnnotateRb
2
- module ModelAnnotator
3
- # This module provides module method to get file paths.
4
- module FilePatterns
5
- # Controller files
6
- CONTROLLER_DIR = File.join('app', 'controllers')
7
-
8
- # Active admin registry files
9
- ACTIVEADMIN_DIR = File.join('app', 'admin')
10
-
11
- # Helper files
12
- HELPER_DIR = File.join('app', 'helpers')
13
-
14
- # File.join for windows reverse bar compat?
15
- # I dont use windows, can`t test
16
- UNIT_TEST_DIR = File.join('test', 'unit')
17
- MODEL_TEST_DIR = File.join('test', 'models') # since rails 4.0
18
- SPEC_MODEL_DIR = File.join('spec', 'models')
19
-
20
- FIXTURE_TEST_DIR = File.join('test', 'fixtures')
21
- FIXTURE_SPEC_DIR = File.join('spec', 'fixtures')
22
-
23
- # Other test files
24
- CONTROLLER_TEST_DIR = File.join('test', 'controllers')
25
- CONTROLLER_SPEC_DIR = File.join('spec', 'controllers')
26
- REQUEST_SPEC_DIR = File.join('spec', 'requests')
27
- ROUTING_SPEC_DIR = File.join('spec', 'routing')
28
-
29
- # Object Daddy http://github.com/flogic/object_daddy/tree/master
30
- EXEMPLARS_TEST_DIR = File.join('test', 'exemplars')
31
- EXEMPLARS_SPEC_DIR = File.join('spec', 'exemplars')
32
-
33
- # Machinist http://github.com/notahat/machinist
34
- BLUEPRINTS_TEST_DIR = File.join('test', 'blueprints')
35
- BLUEPRINTS_SPEC_DIR = File.join('spec', 'blueprints')
36
-
37
- # Factory Bot https://github.com/thoughtbot/factory_bot
38
- FACTORY_BOT_TEST_DIR = File.join('test', 'factories')
39
- FACTORY_BOT_SPEC_DIR = File.join('spec', 'factories')
40
-
41
- # Fabrication https://github.com/paulelliott/fabrication.git
42
- FABRICATORS_TEST_DIR = File.join('test', 'fabricators')
43
- FABRICATORS_SPEC_DIR = File.join('spec', 'fabricators')
44
-
45
- # Serializers https://github.com/rails-api/active_model_serializers
46
- SERIALIZERS_DIR = File.join('app', 'serializers')
47
- SERIALIZERS_TEST_DIR = File.join('test', 'serializers')
48
- SERIALIZERS_SPEC_DIR = File.join('spec', 'serializers')
49
-
50
- class << self
51
- def generate(root_directory, pattern_type, options)
52
- case pattern_type
53
- when 'test' then test_files(root_directory)
54
- when 'fixture' then fixture_files(root_directory)
55
- when 'scaffold' then scaffold_files(root_directory)
56
- when 'factory' then factory_files(root_directory)
57
- when 'serializer' then serialize_files(root_directory)
58
- when 'additional_file_patterns'
59
- [options[:additional_file_patterns] || []].flatten
60
- when 'controller'
61
- [File.join(root_directory, CONTROLLER_DIR, '%PLURALIZED_MODEL_NAME%_controller.rb')]
62
- when 'admin'
63
- [
64
- File.join(root_directory, ACTIVEADMIN_DIR, '%MODEL_NAME%.rb'),
65
- File.join(root_directory, ACTIVEADMIN_DIR, '%PLURALIZED_MODEL_NAME%.rb')
66
- ]
67
- when 'helper'
68
- [File.join(root_directory, HELPER_DIR, '%PLURALIZED_MODEL_NAME%_helper.rb')]
69
- else
70
- []
71
- end
72
- end
73
-
74
- private
75
-
76
- def test_files(root_directory)
77
- [
78
- File.join(root_directory, UNIT_TEST_DIR, '%MODEL_NAME%_test.rb'),
79
- File.join(root_directory, MODEL_TEST_DIR, '%MODEL_NAME%_test.rb'),
80
- File.join(root_directory, SPEC_MODEL_DIR, '%MODEL_NAME%_spec.rb')
81
- ]
82
- end
83
-
84
- def fixture_files(root_directory)
85
- [
86
- File.join(root_directory, FIXTURE_TEST_DIR, '%TABLE_NAME%.yml'),
87
- File.join(root_directory, FIXTURE_SPEC_DIR, '%TABLE_NAME%.yml'),
88
- File.join(root_directory, FIXTURE_TEST_DIR, '%PLURALIZED_MODEL_NAME%.yml'),
89
- File.join(root_directory, FIXTURE_SPEC_DIR, '%PLURALIZED_MODEL_NAME%.yml')
90
- ]
91
- end
92
-
93
- def scaffold_files(root_directory)
94
- [
95
- File.join(root_directory, CONTROLLER_TEST_DIR, '%PLURALIZED_MODEL_NAME%_controller_test.rb'),
96
- File.join(root_directory, CONTROLLER_SPEC_DIR, '%PLURALIZED_MODEL_NAME%_controller_spec.rb'),
97
- File.join(root_directory, REQUEST_SPEC_DIR, '%PLURALIZED_MODEL_NAME%_spec.rb'),
98
- File.join(root_directory, ROUTING_SPEC_DIR, '%PLURALIZED_MODEL_NAME%_routing_spec.rb')
99
- ]
100
- end
101
-
102
- def factory_files(root_directory)
103
- [
104
- File.join(root_directory, EXEMPLARS_TEST_DIR, '%MODEL_NAME%_exemplar.rb'),
105
- File.join(root_directory, EXEMPLARS_SPEC_DIR, '%MODEL_NAME%_exemplar.rb'),
106
- File.join(root_directory, BLUEPRINTS_TEST_DIR, '%MODEL_NAME%_blueprint.rb'),
107
- File.join(root_directory, BLUEPRINTS_SPEC_DIR, '%MODEL_NAME%_blueprint.rb'),
108
- File.join(root_directory, FACTORY_BOT_TEST_DIR, '%MODEL_NAME%_factory.rb'), # (old style)
109
- File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%MODEL_NAME%_factory.rb'), # (old style)
110
- File.join(root_directory, FACTORY_BOT_TEST_DIR, '%TABLE_NAME%.rb'), # (new style)
111
- File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%TABLE_NAME%.rb'), # (new style)
112
- File.join(root_directory, FACTORY_BOT_TEST_DIR, '%PLURALIZED_MODEL_NAME%.rb'), # (new style)
113
- File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%PLURALIZED_MODEL_NAME%.rb'), # (new style)
114
- File.join(root_directory, FABRICATORS_TEST_DIR, '%MODEL_NAME%_fabricator.rb'),
115
- File.join(root_directory, FABRICATORS_SPEC_DIR, '%MODEL_NAME%_fabricator.rb')
116
- ]
117
- end
118
-
119
- def serialize_files(root_directory)
120
- [
121
- File.join(root_directory, SERIALIZERS_DIR, '%MODEL_NAME%_serializer.rb'),
122
- File.join(root_directory, SERIALIZERS_TEST_DIR, '%MODEL_NAME%_serializer_test.rb'),
123
- File.join(root_directory, SERIALIZERS_SPEC_DIR, '%MODEL_NAME%_serializer_spec.rb')
124
- ]
125
- end
126
- end
127
- end
128
- end
129
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- class ForeignKeyAnnotationBuilder
6
- def initialize(model, options)
7
- @model = model
8
- @options = options
9
- end
10
-
11
- def build
12
- fk_info = if @options[:format_markdown]
13
- "#\n# ### Foreign Keys\n#\n"
14
- else
15
- "#\n# Foreign Keys\n#\n"
16
- end
17
-
18
- return '' unless @model.connection.respond_to?(:supports_foreign_keys?) &&
19
- @model.connection.supports_foreign_keys? && @model.connection.respond_to?(:foreign_keys)
20
-
21
- foreign_keys = @model.connection.foreign_keys(@model.table_name)
22
- return '' if foreign_keys.empty?
23
-
24
- format_name = lambda do |fk|
25
- return fk.options[:column] if fk.name.blank?
26
-
27
- @options[:show_complete_foreign_keys] ? fk.name : fk.name.gsub(/(?<=^fk_rails_)[0-9a-f]{10}$/, '...')
28
- end
29
-
30
- max_size = foreign_keys.map(&format_name).map(&:size).max + 1
31
- foreign_keys.sort_by { |fk| [format_name.call(fk), fk.column] }.each do |fk|
32
- ref_info = "#{fk.column} => #{fk.to_table}.#{fk.primary_key}"
33
- constraints_info = ''
34
- constraints_info += "ON DELETE => #{fk.on_delete} " if fk.on_delete
35
- constraints_info += "ON UPDATE => #{fk.on_update} " if fk.on_update
36
- constraints_info = constraints_info.strip
37
-
38
- fk_info += if @options[:format_markdown]
39
- format("# * `%s`%s:\n# * **`%s`**\n",
40
- format_name.call(fk),
41
- constraints_info.blank? ? '' : " (_#{constraints_info}_)",
42
- ref_info)
43
- else
44
- format("# %-#{max_size}.#{max_size}s %s %s",
45
- format_name.call(fk),
46
- "(#{ref_info})",
47
- constraints_info).rstrip + "\n"
48
- end
49
- end
50
-
51
- fk_info
52
- end
53
- end
54
- end
55
- end
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- module Helper
6
- INDEX_CLAUSES = {
7
- unique: {
8
- default: 'UNIQUE',
9
- markdown: '_unique_'
10
- },
11
- where: {
12
- default: 'WHERE',
13
- markdown: '_where_'
14
- },
15
- using: {
16
- default: 'USING',
17
- markdown: '_using_'
18
- }
19
- }.freeze
20
-
21
- class << self
22
- def mb_chars_ljust(string, length)
23
- string = string.to_s
24
- padding = length - Helper.width(string)
25
- if padding.positive?
26
- string + (' ' * padding)
27
- else
28
- string[0..(length - 1)]
29
- end
30
- end
31
-
32
- def index_unique_info(index, format = :default)
33
- index.unique ? " #{INDEX_CLAUSES[:unique][format]}" : ''
34
- end
35
-
36
- def index_where_info(index, format = :default)
37
- value = index.try(:where).try(:to_s)
38
- if value.blank?
39
- ''
40
- else
41
- " #{INDEX_CLAUSES[:where][format]} #{value}"
42
- end
43
- end
44
-
45
- def index_using_info(index, format = :default)
46
- value = index.try(:using) && index.using.try(:to_sym)
47
- if !value.blank? && value != :btree
48
- " #{INDEX_CLAUSES[:using][format]} #{value}"
49
- else
50
- ''
51
- end
52
- end
53
-
54
- def map_col_type_to_ruby_classes(col_type)
55
- case col_type
56
- when 'integer' then Integer.to_s
57
- when 'float' then Float.to_s
58
- when 'decimal' then BigDecimal.to_s
59
- when 'datetime', 'timestamp', 'time' then Time.to_s
60
- when 'date' then Date.to_s
61
- when 'text', 'string', 'binary', 'inet', 'uuid' then String.to_s
62
- when 'json', 'jsonb' then Hash.to_s
63
- when 'boolean' then 'Boolean'
64
- end
65
- end
66
-
67
- def non_ascii_length(string)
68
- string.to_s.chars.reject(&:ascii_only?).length
69
- end
70
-
71
- # Simple quoting for the default column value
72
- def quote(value)
73
- case value
74
- when NilClass then 'NULL'
75
- when TrueClass then 'TRUE'
76
- when FalseClass then 'FALSE'
77
- when Float, Integer then value.to_s
78
- # BigDecimals need to be output in a non-normalized form and quoted.
79
- when BigDecimal then value.to_s('F')
80
- when Array then value.map { |v| quote(v) }
81
- else
82
- value.inspect
83
- end
84
- end
85
-
86
- def width(string)
87
- string.chars.inject(0) { |acc, elem| acc + (elem.bytesize == 3 ? 2 : 1) }
88
- end
89
-
90
- def magic_comments_as_string(content)
91
- magic_comments = content.scan(Constants::MAGIC_COMMENT_MATCHER).flatten.compact
92
-
93
- if magic_comments.any?
94
- magic_comments.join
95
- else
96
- ''
97
- end
98
- end
99
-
100
- # TODO: Find another implementation that doesn't depend on ActiveSupport
101
- def fallback(*args)
102
- args.compact.detect(&:present?)
103
- end
104
- end
105
- end
106
- end
107
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- class IndexAnnotationBuilder
6
- def initialize(model, options)
7
- @model = model
8
- @options = options
9
- end
10
-
11
- def build
12
- index_info = if @options[:format_markdown]
13
- "#\n# ### Indexes\n#\n"
14
- else
15
- "#\n# Indexes\n#\n"
16
- end
17
-
18
- indexes = @model.retrieve_indexes_from_table
19
- return '' if indexes.empty?
20
-
21
- max_size = indexes.collect { |index| index.name.size }.max + 1
22
- indexes.sort_by(&:name).each do |index|
23
- index_info += if @options[:format_markdown]
24
- final_index_string_in_markdown(index)
25
- else
26
- final_index_string(index, max_size)
27
- end
28
- end
29
-
30
- index_info
31
- end
32
-
33
- private
34
-
35
- def final_index_string_in_markdown(index)
36
- details = format(
37
- '%s%s%s',
38
- Helper.index_unique_info(index, :markdown),
39
- Helper.index_where_info(index, :markdown),
40
- Helper.index_using_info(index, :markdown)
41
- ).strip
42
- details = " (#{details})" unless details.blank?
43
-
44
- format(
45
- "# * `%s`%s:\n# * **`%s`**\n",
46
- index.name,
47
- details,
48
- index_columns_info(index).join("`**\n# * **`")
49
- )
50
- end
51
-
52
- def final_index_string(index, max_size)
53
- format(
54
- "# %-#{max_size}.#{max_size}s %s%s%s%s",
55
- index.name,
56
- "(#{index_columns_info(index).join(',')})",
57
- Helper.index_unique_info(index),
58
- Helper.index_where_info(index),
59
- Helper.index_using_info(index)
60
- ).rstrip + "\n"
61
- end
62
-
63
- def index_columns_info(index)
64
- Array(index.columns).map do |col|
65
- if index.try(:orders) && index.orders[col.to_s]
66
- "#{col} #{index.orders[col.to_s].upcase}"
67
- else
68
- col.to_s.gsub("\r", '\r').gsub("\n", '\n')
69
- end
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- module ModelAnnotator
5
- # Annotates a model file and its related files (controllers, factories, etc)
6
- class ModelFileAnnotator
7
- class << self
8
- def call(annotated, file, options)
9
- begin
10
- klass = ModelClassGetter.call(file, options)
11
-
12
- instructions = build_instructions(klass, file, options)
13
- instructions.each do |instruction|
14
- if FileAnnotator.call_with_instructions(instruction)
15
- annotated << instruction.file
16
- end
17
- end
18
-
19
- annotated
20
- rescue BadModelFileError => e
21
- unless options[:ignore_unknown_models]
22
- $stderr.puts "Unable to annotate #{file}: #{e.message}"
23
- $stderr.puts "\t" + e.backtrace.join("\n\t") if options[:trace]
24
- end
25
- rescue StandardError => e
26
- $stderr.puts "Unable to annotate #{file}: #{e.message}"
27
- $stderr.puts "\t" + e.backtrace.join("\n\t") if options[:trace]
28
- end
29
- end
30
-
31
- private
32
-
33
- def build_instructions(klass, file, options = {})
34
- instructions = []
35
-
36
- klass.reset_column_information
37
- annotation = AnnotationGenerator.new(klass, options).generate
38
- model_name = klass.name.underscore
39
- table_name = klass.table_name
40
-
41
- model_instruction = FileAnnotatorInstruction.new(file, annotation, :position_in_class, options)
42
- instructions << model_instruction
43
-
44
- related_files = RelatedFilesListBuilder.new(file, model_name, table_name, options).build
45
- related_file_instructions = related_files.map do |f, position_key|
46
- _instruction = FileAnnotatorInstruction.new(f, annotation, position_key, options)
47
- end
48
- instructions.concat(related_file_instructions)
49
-
50
- instructions
51
- end
52
- end
53
- end
54
- end
55
- end