annotaterb 4.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +0 -0
- data/LICENSE.txt +55 -0
- data/README.md +91 -0
- data/VERSION +1 -0
- data/exe/annotaterb +21 -0
- data/lib/annotate_rb/active_record_patch.rb +9 -0
- data/lib/annotate_rb/commands/annotate_models.rb +22 -0
- data/lib/annotate_rb/commands/annotate_routes.rb +19 -0
- data/lib/annotate_rb/commands/print_help.rb +16 -0
- data/lib/annotate_rb/commands/print_version.rb +12 -0
- data/lib/annotate_rb/commands.rb +10 -0
- data/lib/annotate_rb/config_finder.rb +21 -0
- data/lib/annotate_rb/config_loader.rb +63 -0
- data/lib/annotate_rb/core.rb +23 -0
- data/lib/annotate_rb/eager_loader.rb +23 -0
- data/lib/annotate_rb/env.rb +30 -0
- data/lib/annotate_rb/model_annotator/annotation_pattern_generator.rb +19 -0
- data/lib/annotate_rb/model_annotator/annotator.rb +74 -0
- data/lib/annotate_rb/model_annotator/bad_model_file_error.rb +11 -0
- data/lib/annotate_rb/model_annotator/constants.rb +22 -0
- data/lib/annotate_rb/model_annotator/file_annotation_remover.rb +25 -0
- data/lib/annotate_rb/model_annotator/file_annotator.rb +79 -0
- data/lib/annotate_rb/model_annotator/file_name_resolver.rb +16 -0
- data/lib/annotate_rb/model_annotator/file_patterns.rb +129 -0
- data/lib/annotate_rb/model_annotator/helper.rb +54 -0
- data/lib/annotate_rb/model_annotator/model_class_getter.rb +63 -0
- data/lib/annotate_rb/model_annotator/model_file_annotator.rb +118 -0
- data/lib/annotate_rb/model_annotator/model_files_getter.rb +62 -0
- data/lib/annotate_rb/model_annotator/pattern_getter.rb +27 -0
- data/lib/annotate_rb/model_annotator/schema_info.rb +480 -0
- data/lib/annotate_rb/model_annotator.rb +20 -0
- data/lib/annotate_rb/options.rb +204 -0
- data/lib/annotate_rb/parser.rb +385 -0
- data/lib/annotate_rb/rake_bootstrapper.rb +34 -0
- data/lib/annotate_rb/route_annotator/annotation_processor.rb +56 -0
- data/lib/annotate_rb/route_annotator/annotator.rb +40 -0
- data/lib/annotate_rb/route_annotator/base_processor.rb +104 -0
- data/lib/annotate_rb/route_annotator/header_generator.rb +113 -0
- data/lib/annotate_rb/route_annotator/helper.rb +104 -0
- data/lib/annotate_rb/route_annotator/removal_processor.rb +40 -0
- data/lib/annotate_rb/route_annotator.rb +12 -0
- data/lib/annotate_rb/runner.rb +34 -0
- data/lib/annotate_rb/tasks/annotate_models_migrate.rake +30 -0
- data/lib/annotate_rb.rb +30 -0
- data/lib/generators/annotate_rb/USAGE +4 -0
- data/lib/generators/annotate_rb/install_generator.rb +15 -0
- data/lib/generators/annotate_rb/templates/auto_annotate_models.rake +7 -0
- metadata +96 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
class FileNameResolver
|
6
|
+
class << self
|
7
|
+
def call(filename_template, model_name, table_name)
|
8
|
+
filename_template
|
9
|
+
.gsub('%MODEL_NAME%', model_name)
|
10
|
+
.gsub('%PLURALIZED_MODEL_NAME%', model_name.pluralize)
|
11
|
+
.gsub('%TABLE_NAME%', table_name || model_name.pluralize)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,129 @@
|
|
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
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
module Helper
|
6
|
+
MATCHED_TYPES = %w(test fixture factory serializer scaffold controller helper).freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def matched_types(options)
|
10
|
+
types = MATCHED_TYPES.dup
|
11
|
+
types << 'admin' if options[:active_admin] =~ Constants::TRUE_RE && !types.include?('admin')
|
12
|
+
types << 'additional_file_patterns' if options[:additional_file_patterns].present?
|
13
|
+
|
14
|
+
types
|
15
|
+
end
|
16
|
+
|
17
|
+
def magic_comments_as_string(content)
|
18
|
+
magic_comments = content.scan(Annotator::MAGIC_COMMENT_MATCHER).flatten.compact
|
19
|
+
|
20
|
+
if magic_comments.any?
|
21
|
+
magic_comments.join
|
22
|
+
else
|
23
|
+
''
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def skip_on_migration?
|
28
|
+
Env.read('ANNOTATE_SKIP_ON_DB_MIGRATE') =~ Constants::TRUE_RE || Env.read('skip_on_db_migrate') =~ Constants::TRUE_RE
|
29
|
+
end
|
30
|
+
|
31
|
+
def include_routes?
|
32
|
+
Env.read('routes') =~ Constants::TRUE_RE
|
33
|
+
end
|
34
|
+
|
35
|
+
def include_models?
|
36
|
+
Env.read('models') =~ Constants::TRUE_RE
|
37
|
+
end
|
38
|
+
|
39
|
+
def true?(val)
|
40
|
+
val.present? && Constants::TRUE_RE.match?(val)
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO: Find another implementation that doesn't depend on ActiveSupport
|
44
|
+
def fallback(*args)
|
45
|
+
args.compact.detect(&:present?)
|
46
|
+
end
|
47
|
+
|
48
|
+
def reset_options(options)
|
49
|
+
options.flatten.each { |key| Env.write(key, nil) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
class ModelClassGetter
|
6
|
+
class << self
|
7
|
+
# Retrieve the classes belonging to the model names we're asked to process
|
8
|
+
# Check for namespaced models in subdirectories as well as models
|
9
|
+
# in subdirectories without namespacing.
|
10
|
+
def call(file, options)
|
11
|
+
model_path = file.gsub(/\.rb$/, '')
|
12
|
+
options[:model_dir].each { |dir| model_path = model_path.gsub(/^#{dir}/, '').gsub(/^\//, '') }
|
13
|
+
|
14
|
+
begin
|
15
|
+
get_loaded_model(model_path, file) || raise(BadModelFileError.new)
|
16
|
+
rescue LoadError
|
17
|
+
# this is for non-rails projects, which don't get Rails auto-require magic
|
18
|
+
file_path = File.expand_path(file)
|
19
|
+
if File.file?(file_path) && Kernel.require(file_path)
|
20
|
+
retry
|
21
|
+
elsif model_path =~ /\//
|
22
|
+
model_path = model_path.split('/')[1..-1].join('/').to_s
|
23
|
+
retry
|
24
|
+
else
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Retrieve loaded model class
|
33
|
+
def get_loaded_model(model_path, file)
|
34
|
+
loaded_model_class = get_loaded_model_by_path(model_path)
|
35
|
+
return loaded_model_class if loaded_model_class
|
36
|
+
|
37
|
+
# We cannot get loaded model when `model_path` is loaded by Rails
|
38
|
+
# auto_load/eager_load paths. Try all possible model paths one by one.
|
39
|
+
absolute_file = File.expand_path(file)
|
40
|
+
model_paths =
|
41
|
+
$LOAD_PATH.select { |path| absolute_file.include?(path) }
|
42
|
+
.map { |path| absolute_file.sub(path, '').sub(/\.rb$/, '').sub(/^\//, '') }
|
43
|
+
model_paths
|
44
|
+
.map { |path| get_loaded_model_by_path(path) }
|
45
|
+
.find { |loaded_model| !loaded_model.nil? }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Retrieve loaded model class by path to the file where it's supposed to be defined.
|
49
|
+
def get_loaded_model_by_path(model_path)
|
50
|
+
::ActiveSupport::Inflector.constantize(::ActiveSupport::Inflector.camelize(model_path))
|
51
|
+
rescue StandardError, LoadError
|
52
|
+
# Revert to the old way but it is not really robust
|
53
|
+
ObjectSpace.each_object(::Class)
|
54
|
+
.select do |c|
|
55
|
+
Class === c && # note: we use === to avoid a bug in activesupport 2.3.14 OptionMerger vs. is_a?
|
56
|
+
c.ancestors.respond_to?(:include?) && # to fix FactoryGirl bug, see https://github.com/ctran/annotate_models/pull/82
|
57
|
+
c.ancestors.include?(::ActiveRecord::Base)
|
58
|
+
end.detect { |c| ::ActiveSupport::Inflector.underscore(c.to_s) == model_path }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
# Not sure yet what the difference is between this and FileAnnotator
|
6
|
+
class ModelFileAnnotator
|
7
|
+
class << self
|
8
|
+
def call(annotated, file, header, options)
|
9
|
+
begin
|
10
|
+
return false if /#{Constants::SKIP_ANNOTATION_PREFIX}.*/ =~ (File.exist?(file) ? File.read(file) : '')
|
11
|
+
klass = ModelClassGetter.call(file, options)
|
12
|
+
|
13
|
+
klass_is_a_class = klass.is_a?(Class)
|
14
|
+
klass_inherits_active_record_base = klass < ActiveRecord::Base
|
15
|
+
klass_is_not_abstract = !klass.abstract_class?
|
16
|
+
klass_table_exists = klass.table_exists?
|
17
|
+
|
18
|
+
not_sure_this_conditional = (!options[:exclude_sti_subclasses] || !(klass.superclass < ActiveRecord::Base && klass.table_name == klass.superclass.table_name))
|
19
|
+
|
20
|
+
annotate_conditions = [
|
21
|
+
klass_is_a_class,
|
22
|
+
klass_inherits_active_record_base,
|
23
|
+
not_sure_this_conditional,
|
24
|
+
klass_is_not_abstract,
|
25
|
+
klass_table_exists
|
26
|
+
]
|
27
|
+
|
28
|
+
do_annotate = annotate_conditions.all?
|
29
|
+
|
30
|
+
if do_annotate
|
31
|
+
files_annotated = annotate(klass, file, header, options)
|
32
|
+
annotated.concat(files_annotated)
|
33
|
+
end
|
34
|
+
|
35
|
+
rescue BadModelFileError => e
|
36
|
+
unless options[:ignore_unknown_models]
|
37
|
+
$stderr.puts "Unable to annotate #{file}: #{e.message}"
|
38
|
+
$stderr.puts "\t" + e.backtrace.join("\n\t") if options[:trace]
|
39
|
+
end
|
40
|
+
rescue StandardError => e
|
41
|
+
$stderr.puts "Unable to annotate #{file}: #{e.message}"
|
42
|
+
$stderr.puts "\t" + e.backtrace.join("\n\t") if options[:trace]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Given the name of an ActiveRecord class, create a schema
|
49
|
+
# info block (basically a comment containing information
|
50
|
+
# on the columns and their types) and put it at the front
|
51
|
+
# of the model and fixture source files.
|
52
|
+
#
|
53
|
+
# === Options (opts)
|
54
|
+
# :position_in_class<Symbol>:: where to place the annotated section in model file
|
55
|
+
# :position_in_test<Symbol>:: where to place the annotated section in test/spec file(s)
|
56
|
+
# :position_in_fixture<Symbol>:: where to place the annotated section in fixture file
|
57
|
+
# :position_in_factory<Symbol>:: where to place the annotated section in factory file
|
58
|
+
# :position_in_serializer<Symbol>:: where to place the annotated section in serializer file
|
59
|
+
# :exclude_tests<Symbol>:: whether to skip modification of test/spec files
|
60
|
+
# :exclude_fixtures<Symbol>:: whether to skip modification of fixture files
|
61
|
+
# :exclude_factories<Symbol>:: whether to skip modification of factory files
|
62
|
+
# :exclude_serializers<Symbol>:: whether to skip modification of serializer files
|
63
|
+
# :exclude_scaffolds<Symbol>:: whether to skip modification of scaffold files
|
64
|
+
# :exclude_controllers<Symbol>:: whether to skip modification of controller files
|
65
|
+
# :exclude_helpers<Symbol>:: whether to skip modification of helper files
|
66
|
+
# :exclude_sti_subclasses<Symbol>:: whether to skip modification of files for STI subclasses
|
67
|
+
#
|
68
|
+
# == Returns:
|
69
|
+
# an array of file names that were annotated.
|
70
|
+
#
|
71
|
+
def annotate(klass, file, header, options = {})
|
72
|
+
begin
|
73
|
+
klass.reset_column_information
|
74
|
+
info = SchemaInfo.generate(klass, header, options)
|
75
|
+
model_name = klass.name.underscore
|
76
|
+
table_name = klass.table_name
|
77
|
+
model_file_name = File.join(file)
|
78
|
+
annotated = []
|
79
|
+
|
80
|
+
if FileAnnotator.call(model_file_name, info, :position_in_class, options)
|
81
|
+
annotated << model_file_name
|
82
|
+
end
|
83
|
+
|
84
|
+
Helper.matched_types(options).each do |key|
|
85
|
+
exclusion_key = "exclude_#{key.pluralize}".to_sym
|
86
|
+
position_key = "position_in_#{key}".to_sym
|
87
|
+
|
88
|
+
# Same options for active_admin models
|
89
|
+
if key == 'admin'
|
90
|
+
exclusion_key = 'exclude_class'.to_sym
|
91
|
+
position_key = 'position_in_class'.to_sym
|
92
|
+
end
|
93
|
+
|
94
|
+
next if options[exclusion_key]
|
95
|
+
|
96
|
+
patterns = PatternGetter.call(options, key)
|
97
|
+
|
98
|
+
patterns
|
99
|
+
.map { |f| FileNameResolver.call(f, model_name, table_name) }
|
100
|
+
.map { |f| Dir.glob(f) }
|
101
|
+
.flatten
|
102
|
+
.each do |f|
|
103
|
+
if FileAnnotator.call(f, info, position_key, options)
|
104
|
+
annotated << f
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
rescue StandardError => e
|
109
|
+
$stderr.puts "Unable to annotate #{file}: #{e.message}"
|
110
|
+
$stderr.puts "\t" + e.backtrace.join("\n\t") if options[:trace]
|
111
|
+
end
|
112
|
+
|
113
|
+
annotated
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
class ModelFilesGetter
|
6
|
+
class << self
|
7
|
+
# Return a list of the model files to annotate.
|
8
|
+
# If we have command line arguments, they're assumed to the path
|
9
|
+
# of model files from root dir. Otherwise we take all the model files
|
10
|
+
# in the model_dir directory.
|
11
|
+
def call(options)
|
12
|
+
model_files = []
|
13
|
+
|
14
|
+
model_files = list_model_files_from_argument(options) if !options[:is_rake]
|
15
|
+
|
16
|
+
return model_files if !model_files.empty?
|
17
|
+
|
18
|
+
options[:model_dir].each do |dir|
|
19
|
+
Dir.chdir(dir) do
|
20
|
+
list = if options[:ignore_model_sub_dir]
|
21
|
+
Dir["*.rb"].map { |f| [dir, f] }
|
22
|
+
else
|
23
|
+
Dir["**/*.rb"].reject { |f| f["concerns/"] }.map { |f| [dir, f] }
|
24
|
+
end
|
25
|
+
model_files.concat(list)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
model_files
|
30
|
+
rescue SystemCallError
|
31
|
+
$stderr.puts "No models found in directory '#{options[:model_dir].join("', '")}'."
|
32
|
+
$stderr.puts "Either specify models on the command line, or use the --model-dir option."
|
33
|
+
$stderr.puts "Call 'annotate --help' for more info."
|
34
|
+
# exit 1 # TODO: Return exit code back to caller. Right now it messes up RSpec being able to run
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def list_model_files_from_argument(options)
|
40
|
+
return [] if ARGV.empty?
|
41
|
+
|
42
|
+
specified_files = ARGV.map { |file| File.expand_path(file) }
|
43
|
+
|
44
|
+
model_files = options[:model_dir].flat_map do |dir|
|
45
|
+
absolute_dir_path = File.expand_path(dir)
|
46
|
+
specified_files
|
47
|
+
.find_all { |file| file.start_with?(absolute_dir_path) }
|
48
|
+
.map { |file| [dir, file.sub("#{absolute_dir_path}/", '')] }
|
49
|
+
end
|
50
|
+
|
51
|
+
if model_files.size != specified_files.size
|
52
|
+
$stderr.puts "The specified file could not be found in directory '#{options[:model_dir].join("', '")}'."
|
53
|
+
$stderr.puts "Call 'annotate --help' for more info."
|
54
|
+
# exit 1 # TODO: Return exit code back to caller. Right now it messes up RSpec being able to run
|
55
|
+
end
|
56
|
+
|
57
|
+
model_files
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
class PatternGetter
|
6
|
+
class << self
|
7
|
+
def call(options, pattern_types = [])
|
8
|
+
current_patterns = []
|
9
|
+
|
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)
|
13
|
+
|
14
|
+
current_patterns += if pattern_type.to_sym == :additional_file_patterns
|
15
|
+
patterns
|
16
|
+
else
|
17
|
+
patterns.map { |p| p.sub(/^[\/]*/, '') }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
current_patterns
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|