diff --git a/lib/annotate_rb/model_annotator/model_files_getter.rb b/lib/annotate_rb/model_annotator/model_files_getter.rb index 5e10f6ef..cd0091a2 100644 --- a/lib/annotate_rb/model_annotator/model_files_getter.rb +++ b/lib/annotate_rb/model_annotator/model_files_getter.rb @@ -16,10 +16,14 @@ def call(options) model_dirs = options[:model_dir].flat_map { |model_dir| Dir[model_dir] } model_dirs.each do |dir| Dir.chdir(dir) do + only_files = options[:only_file_patterns]&.map { |pattern| Dir.glob(pattern) }&.flatten list = if options[:ignore_model_sub_dir] - Dir["*.rb"].map { |f| [dir, f] } + Dir["*.rb"] + .select { |f| only_files.nil? || only_files.include?(f) } + .map { |f| [dir, f] } else Dir["**/*.rb"] + .select { |f| only_files.nil? || only_files.include?(f) } .reject { |f| f["concerns/"] } .map { |f| [dir, f] } end diff --git a/lib/annotate_rb/parser.rb b/lib/annotate_rb/parser.rb index da34c4d4..cda32bf7 100644 --- a/lib/annotate_rb/parser.rb +++ b/lib/annotate_rb/parser.rb @@ -376,6 +376,12 @@ def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength @options[:additional_file_patterns] = additional_file_patterns end + option_parser.on("--only-file-patterns path1,path2,path3", + Array, + "If given, restrict annotated models to listed patterns, separated by commas (e.g. `*session*.rb,*login*.rb`)") do |only_file_patterns| + @options[:only_file_patterns] = only_file_patterns + end + option_parser.on("-d", "--delete", "Remove annotations from all model files or the routes.rb file") do diff --git a/spec/integration/annotate_only_file_patterns_spec.rb b/spec/integration/annotate_only_file_patterns_spec.rb new file mode 100644 index 00000000..d9f89c44 --- /dev/null +++ b/spec/integration/annotate_only_file_patterns_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require "integration_spec_helper" + +RSpec.describe "Annotate with only_file_patterns specified", type: "aruba" do + let(:command_timeout_seconds) { 10 } + let(:migration_file) { "20231013230731_add_int_field_to_test_defaults.rb" } + let(:models_dir) { "app/models" } + + it "avoids annotating a model not given" do + reset_database + run_migrations + + # Start with the already annotated TestDefault model + copy(model_template("test_default.rb"), models_dir) + + original_test_default = read_file(dummyapp_model("test_default.rb")) + + copy(File.join(migrations_template_dir, migration_file), "db/migrate") + + # Apply this specific migration + _run_migrations_cmd = run_command_and_stop("bin/rails db:migrate:up VERSION=20231013230731", fail_on_error: true, exit_timeout: command_timeout_seconds) + _run_annotations_cmd = run_command_and_stop("bundle exec annotaterb models --only-file-patterns=nonexistent_model.rb", fail_on_error: true, exit_timeout: command_timeout_seconds) + + annotated_test_default = read_file(dummyapp_model("test_default.rb")) + + # Because the model we restricted ourselves to doesn't exist, we expect the file to remain untouched + expect(last_command_started).to be_successfully_executed + expect(annotated_test_default).to eq(original_test_default) + end +end diff --git a/spec/lib/annotate_rb/parser_spec.rb b/spec/lib/annotate_rb/parser_spec.rb index dbdd92e2..7f19b091 100644 --- a/spec/lib/annotate_rb/parser_spec.rb +++ b/spec/lib/annotate_rb/parser_spec.rb @@ -56,13 +56,14 @@ module AnnotateRb # rubocop:disable Metrics/ModuleLength end end - %w[--additional-file-patterns].each do |option| + %w[--additional-file-patterns --only-file-patterns].each do |option| describe option do + parameter = option.sub("--", "").tr("-", "_").to_sym let(:args) { [option, paths] } let(:paths) { "foo/bar,baz" } - it "sets array of paths to :additional_file_patterns" do - expect(result).to include(additional_file_patterns: ["foo/bar", "baz"]) + it "sets array of paths to :#{parameter}" do + expect(result).to include(parameter => ["foo/bar", "baz"]) end end end