annotaterb 4.1.1 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -0
- data/VERSION +1 -1
- data/exe/annotaterb +7 -7
- data/lib/annotate_rb/active_record_patch.rb +2 -0
- data/lib/annotate_rb/commands/annotate_models.rb +0 -1
- data/lib/annotate_rb/commands/annotate_routes.rb +0 -1
- data/lib/annotate_rb/commands/print_help.rb +0 -1
- data/lib/annotate_rb/commands/print_version.rb +0 -1
- data/lib/annotate_rb/commands.rb +4 -4
- data/lib/annotate_rb/config_finder.rb +1 -1
- data/lib/annotate_rb/config_loader.rb +2 -2
- data/lib/annotate_rb/core.rb +3 -3
- data/lib/annotate_rb/helper.rb +16 -0
- data/lib/annotate_rb/model_annotator/{annotation_generator.rb → annotation_builder.rb} +18 -14
- data/lib/annotate_rb/model_annotator/annotation_decider.rb +10 -12
- data/lib/annotate_rb/model_annotator/annotation_diff.rb +1 -1
- data/lib/annotate_rb/model_annotator/annotation_diff_generator.rb +9 -9
- data/lib/annotate_rb/model_annotator/annotation_pattern_generator.rb +3 -3
- data/lib/annotate_rb/model_annotator/annotator.rb +12 -53
- data/lib/annotate_rb/model_annotator/column_annotation/annotation_builder.rb +135 -0
- data/lib/annotate_rb/model_annotator/column_annotation/attributes_builder.rb +104 -0
- data/lib/annotate_rb/model_annotator/column_annotation/column_wrapper.rb +103 -0
- data/lib/annotate_rb/model_annotator/column_annotation/type_builder.rb +54 -0
- data/lib/annotate_rb/model_annotator/column_annotation.rb +12 -0
- data/lib/annotate_rb/model_annotator/file_builder.rb +58 -0
- data/lib/annotate_rb/model_annotator/file_components.rb +78 -0
- data/lib/annotate_rb/model_annotator/file_name_resolver.rb +3 -3
- data/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder.rb +57 -0
- data/lib/annotate_rb/model_annotator/foreign_key_annotation.rb +9 -0
- data/lib/annotate_rb/model_annotator/index_annotation/annotation_builder.rb +113 -0
- data/lib/annotate_rb/model_annotator/index_annotation.rb +9 -0
- data/lib/annotate_rb/model_annotator/magic_comment_parser.rb +32 -0
- data/lib/annotate_rb/model_annotator/model_class_getter.rb +6 -6
- data/lib/annotate_rb/model_annotator/model_files_getter.rb +12 -10
- data/lib/annotate_rb/model_annotator/model_wrapper.rb +44 -37
- data/lib/annotate_rb/model_annotator/pattern_getter.rb +142 -10
- data/lib/annotate_rb/model_annotator/project_annotation_remover.rb +65 -0
- data/lib/annotate_rb/model_annotator/project_annotator.rb +63 -0
- data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +16 -18
- data/lib/annotate_rb/model_annotator/single_file_annotation_remover.rb +37 -0
- data/lib/annotate_rb/model_annotator/single_file_annotator.rb +49 -0
- data/lib/annotate_rb/model_annotator/{file_annotator_instruction.rb → single_file_annotator_instruction.rb} +2 -2
- data/lib/annotate_rb/model_annotator/single_file_remove_annotation_instruction.rb +15 -0
- data/lib/annotate_rb/model_annotator.rb +25 -26
- data/lib/annotate_rb/options.rb +20 -25
- data/lib/annotate_rb/parser.rb +150 -142
- data/lib/annotate_rb/rake_bootstrapper.rb +8 -8
- data/lib/annotate_rb/route_annotator/annotation_processor.rb +7 -8
- data/lib/annotate_rb/route_annotator/annotator.rb +2 -2
- data/lib/annotate_rb/route_annotator/base_processor.rb +3 -3
- data/lib/annotate_rb/route_annotator/header_generator.rb +15 -15
- data/lib/annotate_rb/route_annotator/helper.rb +9 -9
- data/lib/annotate_rb/route_annotator/removal_processor.rb +4 -4
- data/lib/annotate_rb/route_annotator.rb +6 -6
- data/lib/annotate_rb/runner.rb +0 -4
- data/lib/annotate_rb/tasks/annotate_models_migrate.rake +5 -5
- data/lib/annotate_rb.rb +19 -19
- data/lib/generators/annotate_rb/install/install_generator.rb +3 -2
- data/lib/generators/annotate_rb/install/templates/annotate_rb.rake +1 -1
- metadata +22 -16
- data/lib/annotate_rb/model_annotator/column_annotation_builder.rb +0 -92
- data/lib/annotate_rb/model_annotator/column_attributes_builder.rb +0 -102
- data/lib/annotate_rb/model_annotator/column_type_builder.rb +0 -51
- data/lib/annotate_rb/model_annotator/column_wrapper.rb +0 -84
- data/lib/annotate_rb/model_annotator/constants.rb +0 -22
- data/lib/annotate_rb/model_annotator/file_annotation_remover.rb +0 -25
- data/lib/annotate_rb/model_annotator/file_annotator.rb +0 -77
- data/lib/annotate_rb/model_annotator/file_patterns.rb +0 -129
- data/lib/annotate_rb/model_annotator/foreign_key_annotation_builder.rb +0 -55
- data/lib/annotate_rb/model_annotator/helper.rb +0 -107
- data/lib/annotate_rb/model_annotator/index_annotation_builder.rb +0 -74
- 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
|