From f6d47735b1a61d11b0f9ea1499058ae80ee1f872 Mon Sep 17 00:00:00 2001 From: Takumi Shotoku Date: Mon, 24 Feb 2025 22:31:08 +0900 Subject: [PATCH] Support the glob pattern in `root_dir` and `model_dir` We often want to specify multiple directories in `root_dir` and `model_dir`. For example, when using engines, packs-rails, etc. * https://github.com/rubyatscale/packs-rails * https://guides.rubyonrails.org/engines.html This commit supports the glob pattern with these options, making it easy to specify multiple directories. fixes #99 --- lib/annotate_rb/eager_loader.rb | 7 ++--- .../model_annotator/model_files_getter.rb | 17 ++++++----- .../model_annotator/pattern_getter.rb | 5 +++- .../model_files_getter_spec.rb | 28 +++++++++++++++++ .../model_annotator/pattern_getter_spec.rb | 30 +++++++++++++++++++ 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/lib/annotate_rb/eager_loader.rb b/lib/annotate_rb/eager_loader.rb index a94ba407..dfdc0912 100644 --- a/lib/annotate_rb/eager_loader.rb +++ b/lib/annotate_rb/eager_loader.rb @@ -15,10 +15,9 @@ def call(options) klass.eager_load! end else - options[:model_dir].each do |dir| - ::Rake::FileList["#{dir}/**/*.rb"].each do |fname| - require File.expand_path(fname) - end + model_files = ModelAnnotator::ModelFilesGetter.call(options) + model_files&.each do |model_file| + require model_file end end end diff --git a/lib/annotate_rb/model_annotator/model_files_getter.rb b/lib/annotate_rb/model_annotator/model_files_getter.rb index 307db8e0..397e5be9 100644 --- a/lib/annotate_rb/model_annotator/model_files_getter.rb +++ b/lib/annotate_rb/model_annotator/model_files_getter.rb @@ -13,7 +13,8 @@ def call(options) return model_files if model_files.any? - options[:model_dir].each do |dir| + model_dirs = options[:model_dir].flat_map { |model_dir| Dir[model_dir] } + model_dirs.each do |dir| Dir.chdir(dir) do list = if options[:ignore_model_sub_dir] Dir["*.rb"].map { |f| [dir, f] } @@ -26,12 +27,14 @@ def call(options) end end - model_files - rescue SystemCallError - warn "No models found in directory '#{options[:model_dir].join("', '")}'." - warn "Either specify models on the command line, or use the --model-dir option." - warn "Call 'annotaterb --help' for more info." - # exit 1 # TODO: Return exit code back to caller. Right now it messes up RSpec being able to run + if model_files.empty? + warn "No models found in directory '#{options[:model_dir].join("', '")}'." + warn "Either specify models on the command line, or use the --model-dir option." + warn "Call 'annotaterb --help' for more info." + # exit 1 # TODO: Return exit code back to caller. Right now it messes up RSpec being able to run + else + model_files + end end private diff --git a/lib/annotate_rb/model_annotator/pattern_getter.rb b/lib/annotate_rb/model_annotator/pattern_getter.rb index 4cf8278e..de8eb538 100644 --- a/lib/annotate_rb/model_annotator/pattern_getter.rb +++ b/lib/annotate_rb/model_annotator/pattern_getter.rb @@ -64,7 +64,10 @@ def initialize(options, pattern_types = []) def get current_patterns = [] - @options[:root_dir].each do |root_directory| + root_dirs = @options[:root_dir].flat_map do |root_dir| + root_dir.empty? ? root_dir : Dir[root_dir] + end + root_dirs.each do |root_directory| Array(@pattern_types).each do |pattern_type| patterns = generate(root_directory, pattern_type) diff --git a/spec/lib/annotate_rb/model_annotator/model_files_getter_spec.rb b/spec/lib/annotate_rb/model_annotator/model_files_getter_spec.rb index 5a459836..c899eef5 100644 --- a/spec/lib/annotate_rb/model_annotator/model_files_getter_spec.rb +++ b/spec/lib/annotate_rb/model_annotator/model_files_getter_spec.rb @@ -94,5 +94,33 @@ expect($stderr.string).to include("No models found in directory") end end + + context "when `model_dir` is the glob pattern" do + let(:base_options) { {model_dir: ["app/models", "packs/*/app/models"]} } + let(:options) { AnnotateRb::Options.new(base_options, {working_args: []}) } + + around do |example| + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + FileUtils.mkdir_p(File.join("app", "models")) + FileUtils.touch(File.join("app", "models", "x.rb")) + FileUtils.mkdir_p(File.join("packs", "foo", "app", "models")) + FileUtils.touch(File.join("packs", "foo", "app", "models", "y.rb")) + FileUtils.mkdir_p(File.join("packs", "bar", "app", "models")) + FileUtils.touch(File.join("packs", "bar", "app", "models", "z.rb")) + + example.run + end + end + end + + it "returns all model files under directories that matches the glob pattern" do + is_expected.to contain_exactly( + ["app/models", "x.rb"], + ["packs/bar/app/models", "z.rb"], + ["packs/foo/app/models", "y.rb"] + ) + end + end end end diff --git a/spec/lib/annotate_rb/model_annotator/pattern_getter_spec.rb b/spec/lib/annotate_rb/model_annotator/pattern_getter_spec.rb index 8d25a3b0..18252d22 100644 --- a/spec/lib/annotate_rb/model_annotator/pattern_getter_spec.rb +++ b/spec/lib/annotate_rb/model_annotator/pattern_getter_spec.rb @@ -181,5 +181,35 @@ ]) end end + + context 'when root_dir is the glob pattern' do + let(:base_options) { {root_dir: ["", "packs/*"]} } + let(:pattern_type) { "test" } + + around do |example| + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + FileUtils.mkdir_p("packs/foo") + FileUtils.mkdir_p("packs/bar") + FileUtils.touch(File.join(dir, "foo.rb")) + example.run + end + end + end + + it "returns patterns with the glob pattern expanded" do + is_expected.to eq([ + "test/unit/%MODEL_NAME%_test.rb", + "test/models/%MODEL_NAME%_test.rb", + "spec/models/%MODEL_NAME%_spec.rb", + "packs/bar/test/unit/%MODEL_NAME%_test.rb", + "packs/bar/test/models/%MODEL_NAME%_test.rb", + "packs/bar/spec/models/%MODEL_NAME%_spec.rb", + "packs/foo/test/unit/%MODEL_NAME%_test.rb", + "packs/foo/test/models/%MODEL_NAME%_test.rb", + "packs/foo/spec/models/%MODEL_NAME%_spec.rb" + ]) + end + end end end