Skip to content

Commit cdb35df

Browse files
ryanwjacksonvfonic
authored andcommitted
Add option for additional file patterns (ctran#633)
This PR adds an option named `additional_file_patterns`. You can specify custom path patterns (including globs) that the gem will use to annotate. For example, I used it like this on a project: ```ruby Annotate.set_defaults( 'additional_file_patterns' => [ File.join(Rails.application.root, 'app/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb'), File.join(Rails.application.root, 'spec/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb') ], ... ) ``` This makes it possible to have files nested under a directory which corresponds to the model. I believe this fixes ctran#594.
1 parent 7c4f825 commit cdb35df

File tree

4 files changed

+149
-49
lines changed

4 files changed

+149
-49
lines changed

lib/annotate.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ module Annotate
3636
:exclude_sti_subclasses, :ignore_unknown_models, :with_comment
3737
].freeze
3838
OTHER_OPTIONS = [
39-
:ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close,
39+
:additional_file_patterns, :ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close,
4040
:wrapper, :routes, :hide_limit_column_types, :hide_default_column_types,
4141
:ignore_routes, :active_admin
4242
].freeze
@@ -88,6 +88,7 @@ def self.setup_options(options = {})
8888
options[key] = !ENV[key.to_s].blank? ? ENV[key.to_s].split(',') : []
8989
end
9090

91+
options[:additional_file_patterns] ||= []
9192
options[:model_dir] = ['app/models'] if options[:model_dir].empty?
9293

9394
options[:wrapper_open] ||= options[:wrapper]

lib/annotate/annotate_models.rb

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,15 @@ def serialize_files(root_directory)
159159
]
160160
end
161161

162-
def files_by_pattern(root_directory, pattern_type)
162+
def files_by_pattern(root_directory, pattern_type, options)
163163
case pattern_type
164164
when 'test' then test_files(root_directory)
165165
when 'fixture' then fixture_files(root_directory)
166166
when 'scaffold' then scaffold_files(root_directory)
167167
when 'factory' then factory_files(root_directory)
168168
when 'serializer' then serialize_files(root_directory)
169+
when 'additional_file_patterns'
170+
[options[:additional_file_patterns] || []].flatten
169171
when 'controller'
170172
[File.join(root_directory, CONTROLLER_DIR, "%PLURALIZED_MODEL_NAME%_controller.rb")]
171173
when 'admin'
@@ -177,14 +179,20 @@ def files_by_pattern(root_directory, pattern_type)
177179
end
178180
end
179181

180-
def get_patterns(pattern_types = [])
182+
def get_patterns(options, pattern_types = [])
181183
current_patterns = []
182184
root_dir.each do |root_directory|
183185
Array(pattern_types).each do |pattern_type|
184-
current_patterns += files_by_pattern(root_directory, pattern_type)
186+
patterns = files_by_pattern(root_directory, pattern_type, options)
187+
188+
current_patterns += if pattern_type.to_sym == :additional_file_patterns
189+
patterns
190+
else
191+
patterns.map { |p| p.sub(/^[\/]*/, '') }
192+
end
185193
end
186194
end
187-
current_patterns.map { |p| p.sub(/^[\/]*/, '') }
195+
current_patterns
188196
end
189197

190198
# Simple quoting for the default column value
@@ -581,8 +589,9 @@ def remove_annotation_of_file(file_name, options = {})
581589
end
582590

583591
def matched_types(options)
584-
types = MATCHED_TYPES
592+
types = MATCHED_TYPES.dup
585593
types << 'admin' if options[:active_admin] =~ TRUE_RE && !types.include?('admin')
594+
types << 'additional_file_patterns' if options[:additional_file_patterns].present?
586595

587596
types
588597
end
@@ -634,8 +643,11 @@ def annotate(klass, file, header, options = {})
634643
end
635644

636645
next if options[exclusion_key]
637-
get_patterns(key)
646+
647+
get_patterns(options, key)
638648
.map { |f| resolve_filename(f, model_name, table_name) }
649+
.map { |f| expand_glob_into_files(f) }
650+
.flatten
639651
.each do |f|
640652
if annotate_one_file(f, info, position_key, options_with_position(options, position_key))
641653
annotated << f
@@ -793,6 +805,10 @@ def do_annotations(options = {})
793805
end
794806
end
795807

808+
def expand_glob_into_files(glob)
809+
Dir.glob(glob)
810+
end
811+
796812
def annotate_model_file(annotated, file, header, options)
797813
begin
798814
return false if /#{SKIP_ANNOTATION_PREFIX}.*/ =~ (File.exist?(file) ? File.read(file) : '')
@@ -830,7 +846,7 @@ def remove_annotations(options = {})
830846
model_file_name = file
831847
deannotated_klass = true if remove_annotation_of_file(model_file_name, options)
832848

833-
get_patterns(matched_types(options))
849+
get_patterns(options, matched_types(options))
834850
.map { |f| resolve_filename(f, model_name, table_name) }
835851
.each do |f|
836852
if File.exist?(f)

lib/generators/annotate/templates/auto_annotate_models.rake

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,47 +7,48 @@ if Rails.env.development?
77
# You can override any of these by setting an environment variable of the
88
# same name.
99
Annotate.set_defaults(
10-
'routes' => 'false',
11-
'position_in_routes' => 'before',
12-
'position_in_class' => 'before',
13-
'position_in_test' => 'before',
14-
'position_in_fixture' => 'before',
15-
'position_in_factory' => 'before',
16-
'position_in_serializer' => 'before',
17-
'show_foreign_keys' => 'true',
18-
'show_complete_foreign_keys' => 'false',
19-
'show_indexes' => 'true',
20-
'simple_indexes' => 'false',
21-
'model_dir' => 'app/models',
22-
'root_dir' => '',
23-
'include_version' => 'false',
24-
'require' => '',
25-
'exclude_tests' => 'false',
26-
'exclude_fixtures' => 'false',
27-
'exclude_factories' => 'false',
28-
'exclude_serializers' => 'false',
29-
'exclude_scaffolds' => 'true',
30-
'exclude_controllers' => 'true',
31-
'exclude_helpers' => 'true',
32-
'exclude_sti_subclasses' => 'false',
33-
'ignore_model_sub_dir' => 'false',
34-
'ignore_columns' => nil,
35-
'ignore_routes' => nil,
36-
'ignore_unknown_models' => 'false',
37-
'hide_limit_column_types' => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(",") %>',
38-
'hide_default_column_types' => '<%= AnnotateModels::NO_DEFAULT_COL_TYPES.join(",") %>',
39-
'skip_on_db_migrate' => 'false',
40-
'format_bare' => 'true',
41-
'format_rdoc' => 'false',
42-
'format_markdown' => 'false',
43-
'sort' => 'false',
44-
'force' => 'false',
45-
'frozen' => 'false',
46-
'classified_sort' => 'true',
47-
'trace' => 'false',
48-
'wrapper_open' => nil,
49-
'wrapper_close' => nil,
50-
'with_comment' => 'true'
10+
'additional_file_patterns' => [],
11+
'routes' => 'false',
12+
'position_in_routes' => 'before',
13+
'position_in_class' => 'before',
14+
'position_in_test' => 'before',
15+
'position_in_fixture' => 'before',
16+
'position_in_factory' => 'before',
17+
'position_in_serializer' => 'before',
18+
'show_foreign_keys' => 'true',
19+
'show_complete_foreign_keys' => 'false',
20+
'show_indexes' => 'true',
21+
'simple_indexes' => 'false',
22+
'model_dir' => 'app/models',
23+
'root_dir' => '',
24+
'include_version' => 'false',
25+
'require' => '',
26+
'exclude_tests' => 'false',
27+
'exclude_fixtures' => 'false',
28+
'exclude_factories' => 'false',
29+
'exclude_serializers' => 'false',
30+
'exclude_scaffolds' => 'true',
31+
'exclude_controllers' => 'true',
32+
'exclude_helpers' => 'true',
33+
'exclude_sti_subclasses' => 'false',
34+
'ignore_model_sub_dir' => 'false',
35+
'ignore_columns' => nil,
36+
'ignore_routes' => nil,
37+
'ignore_unknown_models' => 'false',
38+
'hide_limit_column_types' => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(",") %>',
39+
'hide_default_column_types' => '<%= AnnotateModels::NO_DEFAULT_COL_TYPES.join(",") %>',
40+
'skip_on_db_migrate' => 'false',
41+
'format_bare' => 'true',
42+
'format_rdoc' => 'false',
43+
'format_markdown' => 'false',
44+
'sort' => 'false',
45+
'force' => 'false',
46+
'frozen' => 'false',
47+
'classified_sort' => 'true',
48+
'trace' => 'false',
49+
'wrapper_open' => nil,
50+
'wrapper_close' => nil,
51+
'with_comment' => 'true'
5152
)
5253
end
5354

spec/annotate/annotate_models_spec.rb

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,69 @@ def mock_column(name, type, options = {})
780780
end
781781
end
782782

783+
describe '#files_by_pattern' do
784+
subject { AnnotateModels.files_by_pattern(root_directory, pattern_type, options) }
785+
786+
context 'when pattern_type=additional_file_patterns' do
787+
let(:pattern_type) { 'additional_file_patterns' }
788+
let(:root_directory) { nil }
789+
790+
context 'with additional_file_patterns' do
791+
let(:additional_file_patterns) do
792+
[
793+
'%PLURALIZED_MODEL_NAME%/**/*.rb',
794+
'%PLURALIZED_MODEL_NAME%/*_form'
795+
]
796+
end
797+
798+
let(:options) { { additional_file_patterns: additional_file_patterns } }
799+
800+
it do
801+
expect(subject).to eq(additional_file_patterns)
802+
end
803+
end
804+
805+
context 'without additional_file_patterns' do
806+
let(:options) { {} }
807+
808+
it do
809+
expect(subject).to eq([])
810+
end
811+
end
812+
end
813+
end
814+
815+
describe '#get_patterns' do
816+
subject { AnnotateModels.get_patterns(options, pattern_type) }
817+
818+
context 'when pattern_type=additional_file_patterns' do
819+
let(:pattern_type) { 'additional_file_patterns' }
820+
821+
context 'with additional_file_patterns' do
822+
let(:additional_file_patterns) do
823+
[
824+
'/%PLURALIZED_MODEL_NAME%/**/*.rb',
825+
'/bar/%PLURALIZED_MODEL_NAME%/*_form'
826+
]
827+
end
828+
829+
let(:options) { { additional_file_patterns: additional_file_patterns } }
830+
831+
it do
832+
expect(subject).to eq(additional_file_patterns)
833+
end
834+
end
835+
836+
context 'without additional_file_patterns' do
837+
let(:options) { {} }
838+
839+
it do
840+
expect(subject).to eq([])
841+
end
842+
end
843+
end
844+
end
845+
783846
describe '#get_schema_info with custom options' do
784847
def self.when_called_with(options = {})
785848
expected = options.delete(:returns)
@@ -1505,6 +1568,24 @@ class Foo < ActiveRecord::Base
15051568
expect(filename). to eq 'test/unit/example_model_test.rb'
15061569
end
15071570

1571+
it 'should return the additional glob' do
1572+
filename_template = '/foo/bar/%MODEL_NAME%/testing.rb'
1573+
model_name = 'example_model'
1574+
table_name = 'example_models'
1575+
1576+
filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
1577+
expect(filename). to eq '/foo/bar/example_model/testing.rb'
1578+
end
1579+
1580+
it 'should return the additional glob' do
1581+
filename_template = '/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb'
1582+
model_name = 'example_model'
1583+
table_name = 'example_models'
1584+
1585+
filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
1586+
expect(filename). to eq '/foo/bar/example_models/testing.rb'
1587+
end
1588+
15081589
it 'should return the fixture path for a model' do
15091590
filename_template = 'test/fixtures/%TABLE_NAME%.yml'
15101591
model_name = 'example_model'
@@ -1523,6 +1604,7 @@ class Foo < ActiveRecord::Base
15231604
expect(filename). to eq 'test/fixtures/parent/children.yml'
15241605
end
15251606
end
1607+
15261608
describe 'annotating a file' do
15271609
before do
15281610
@model_dir = Dir.mktmpdir('annotate_models')

0 commit comments

Comments
 (0)