Skip to content

Commit

Permalink
Add option for additional file patterns (ctran#633)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ryanwjackson authored and vfonic committed May 8, 2020
1 parent 7c4f825 commit cdb35df
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 49 deletions.
3 changes: 2 additions & 1 deletion lib/annotate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module Annotate
:exclude_sti_subclasses, :ignore_unknown_models, :with_comment
].freeze
OTHER_OPTIONS = [
:ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close,
:additional_file_patterns, :ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close,
:wrapper, :routes, :hide_limit_column_types, :hide_default_column_types,
:ignore_routes, :active_admin
].freeze
Expand Down Expand Up @@ -88,6 +88,7 @@ def self.setup_options(options = {})
options[key] = !ENV[key.to_s].blank? ? ENV[key.to_s].split(',') : []
end

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

options[:wrapper_open] ||= options[:wrapper]
Expand Down
30 changes: 23 additions & 7 deletions lib/annotate/annotate_models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,15 @@ def serialize_files(root_directory)
]
end

def files_by_pattern(root_directory, pattern_type)
def files_by_pattern(root_directory, pattern_type, options)
case pattern_type
when 'test' then test_files(root_directory)
when 'fixture' then fixture_files(root_directory)
when 'scaffold' then scaffold_files(root_directory)
when 'factory' then factory_files(root_directory)
when 'serializer' then serialize_files(root_directory)
when 'additional_file_patterns'
[options[:additional_file_patterns] || []].flatten
when 'controller'
[File.join(root_directory, CONTROLLER_DIR, "%PLURALIZED_MODEL_NAME%_controller.rb")]
when 'admin'
Expand All @@ -177,14 +179,20 @@ def files_by_pattern(root_directory, pattern_type)
end
end

def get_patterns(pattern_types = [])
def get_patterns(options, pattern_types = [])
current_patterns = []
root_dir.each do |root_directory|
Array(pattern_types).each do |pattern_type|
current_patterns += files_by_pattern(root_directory, pattern_type)
patterns = files_by_pattern(root_directory, pattern_type, options)

current_patterns += if pattern_type.to_sym == :additional_file_patterns
patterns
else
patterns.map { |p| p.sub(/^[\/]*/, '') }
end
end
end
current_patterns.map { |p| p.sub(/^[\/]*/, '') }
current_patterns
end

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

def matched_types(options)
types = MATCHED_TYPES
types = MATCHED_TYPES.dup
types << 'admin' if options[:active_admin] =~ TRUE_RE && !types.include?('admin')
types << 'additional_file_patterns' if options[:additional_file_patterns].present?

types
end
Expand Down Expand Up @@ -634,8 +643,11 @@ def annotate(klass, file, header, options = {})
end

next if options[exclusion_key]
get_patterns(key)

get_patterns(options, key)
.map { |f| resolve_filename(f, model_name, table_name) }
.map { |f| expand_glob_into_files(f) }
.flatten
.each do |f|
if annotate_one_file(f, info, position_key, options_with_position(options, position_key))
annotated << f
Expand Down Expand Up @@ -793,6 +805,10 @@ def do_annotations(options = {})
end
end

def expand_glob_into_files(glob)
Dir.glob(glob)
end

def annotate_model_file(annotated, file, header, options)
begin
return false if /#{SKIP_ANNOTATION_PREFIX}.*/ =~ (File.exist?(file) ? File.read(file) : '')
Expand Down Expand Up @@ -830,7 +846,7 @@ def remove_annotations(options = {})
model_file_name = file
deannotated_klass = true if remove_annotation_of_file(model_file_name, options)

get_patterns(matched_types(options))
get_patterns(options, matched_types(options))
.map { |f| resolve_filename(f, model_name, table_name) }
.each do |f|
if File.exist?(f)
Expand Down
83 changes: 42 additions & 41 deletions lib/generators/annotate/templates/auto_annotate_models.rake
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,48 @@ if Rails.env.development?
# You can override any of these by setting an environment variable of the
# same name.
Annotate.set_defaults(
'routes' => 'false',
'position_in_routes' => 'before',
'position_in_class' => 'before',
'position_in_test' => 'before',
'position_in_fixture' => 'before',
'position_in_factory' => 'before',
'position_in_serializer' => 'before',
'show_foreign_keys' => 'true',
'show_complete_foreign_keys' => 'false',
'show_indexes' => 'true',
'simple_indexes' => 'false',
'model_dir' => 'app/models',
'root_dir' => '',
'include_version' => 'false',
'require' => '',
'exclude_tests' => 'false',
'exclude_fixtures' => 'false',
'exclude_factories' => 'false',
'exclude_serializers' => 'false',
'exclude_scaffolds' => 'true',
'exclude_controllers' => 'true',
'exclude_helpers' => 'true',
'exclude_sti_subclasses' => 'false',
'ignore_model_sub_dir' => 'false',
'ignore_columns' => nil,
'ignore_routes' => nil,
'ignore_unknown_models' => 'false',
'hide_limit_column_types' => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(",") %>',
'hide_default_column_types' => '<%= AnnotateModels::NO_DEFAULT_COL_TYPES.join(",") %>',
'skip_on_db_migrate' => 'false',
'format_bare' => 'true',
'format_rdoc' => 'false',
'format_markdown' => 'false',
'sort' => 'false',
'force' => 'false',
'frozen' => 'false',
'classified_sort' => 'true',
'trace' => 'false',
'wrapper_open' => nil,
'wrapper_close' => nil,
'with_comment' => 'true'
'additional_file_patterns' => [],
'routes' => 'false',
'position_in_routes' => 'before',
'position_in_class' => 'before',
'position_in_test' => 'before',
'position_in_fixture' => 'before',
'position_in_factory' => 'before',
'position_in_serializer' => 'before',
'show_foreign_keys' => 'true',
'show_complete_foreign_keys' => 'false',
'show_indexes' => 'true',
'simple_indexes' => 'false',
'model_dir' => 'app/models',
'root_dir' => '',
'include_version' => 'false',
'require' => '',
'exclude_tests' => 'false',
'exclude_fixtures' => 'false',
'exclude_factories' => 'false',
'exclude_serializers' => 'false',
'exclude_scaffolds' => 'true',
'exclude_controllers' => 'true',
'exclude_helpers' => 'true',
'exclude_sti_subclasses' => 'false',
'ignore_model_sub_dir' => 'false',
'ignore_columns' => nil,
'ignore_routes' => nil,
'ignore_unknown_models' => 'false',
'hide_limit_column_types' => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(",") %>',
'hide_default_column_types' => '<%= AnnotateModels::NO_DEFAULT_COL_TYPES.join(",") %>',
'skip_on_db_migrate' => 'false',
'format_bare' => 'true',
'format_rdoc' => 'false',
'format_markdown' => 'false',
'sort' => 'false',
'force' => 'false',
'frozen' => 'false',
'classified_sort' => 'true',
'trace' => 'false',
'wrapper_open' => nil,
'wrapper_close' => nil,
'with_comment' => 'true'
)
end

Expand Down
82 changes: 82 additions & 0 deletions spec/annotate/annotate_models_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,69 @@ def mock_column(name, type, options = {})
end
end

describe '#files_by_pattern' do
subject { AnnotateModels.files_by_pattern(root_directory, pattern_type, options) }

context 'when pattern_type=additional_file_patterns' do
let(:pattern_type) { 'additional_file_patterns' }
let(:root_directory) { nil }

context 'with additional_file_patterns' do
let(:additional_file_patterns) do
[
'%PLURALIZED_MODEL_NAME%/**/*.rb',
'%PLURALIZED_MODEL_NAME%/*_form'
]
end

let(:options) { { additional_file_patterns: additional_file_patterns } }

it do
expect(subject).to eq(additional_file_patterns)
end
end

context 'without additional_file_patterns' do
let(:options) { {} }

it do
expect(subject).to eq([])
end
end
end
end

describe '#get_patterns' do
subject { AnnotateModels.get_patterns(options, pattern_type) }

context 'when pattern_type=additional_file_patterns' do
let(:pattern_type) { 'additional_file_patterns' }

context 'with additional_file_patterns' do
let(:additional_file_patterns) do
[
'/%PLURALIZED_MODEL_NAME%/**/*.rb',
'/bar/%PLURALIZED_MODEL_NAME%/*_form'
]
end

let(:options) { { additional_file_patterns: additional_file_patterns } }

it do
expect(subject).to eq(additional_file_patterns)
end
end

context 'without additional_file_patterns' do
let(:options) { {} }

it do
expect(subject).to eq([])
end
end
end
end

describe '#get_schema_info with custom options' do
def self.when_called_with(options = {})
expected = options.delete(:returns)
Expand Down Expand Up @@ -1505,6 +1568,24 @@ class Foo < ActiveRecord::Base
expect(filename). to eq 'test/unit/example_model_test.rb'
end

it 'should return the additional glob' do
filename_template = '/foo/bar/%MODEL_NAME%/testing.rb'
model_name = 'example_model'
table_name = 'example_models'

filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
expect(filename). to eq '/foo/bar/example_model/testing.rb'
end

it 'should return the additional glob' do
filename_template = '/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb'
model_name = 'example_model'
table_name = 'example_models'

filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name)
expect(filename). to eq '/foo/bar/example_models/testing.rb'
end

it 'should return the fixture path for a model' do
filename_template = 'test/fixtures/%TABLE_NAME%.yml'
model_name = 'example_model'
Expand All @@ -1523,6 +1604,7 @@ class Foo < ActiveRecord::Base
expect(filename). to eq 'test/fixtures/parent/children.yml'
end
end

describe 'annotating a file' do
before do
@model_dir = Dir.mktmpdir('annotate_models')
Expand Down

0 comments on commit cdb35df

Please sign in to comment.