Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions lib/annotate_rb/model_annotator/related_files_list_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,33 @@ def related_files_for_pattern(pattern_type)

patterns
.map { |f| FileNameResolver.call(f, @model_name, @table_name) }
.map { |f| Dir.glob(f) }
.flatten
.flat_map { |f| Dir.glob(f) }
.select { |f| owning_root_dir(f) == model_root_dir }
end

def model_root_dir
return @model_root_dir if defined?(@model_root_dir)

@model_root_dir = owning_root_dir(@file)
end

# Patterns are expanded for every `root_dir` and resolved by model name alone, so models sharing a
# file basename across root directories (e.g. packwerk packs) glob the same related files. Root
# directories can be nested, so a file belongs to the most specific one containing it, and only
# models from that same root directory may annotate it. Returns nil for the project root.
def owning_root_dir(file)
expanded_file = File.expand_path(file)

expanded_root_dirs
.select { |dir| expanded_file.start_with?("#{dir}/") }
.max_by(&:length)
end

def expanded_root_dirs
@expanded_root_dirs ||= Array(@options[:root_dir])
.reject { |root_dir| root_dir.to_s.empty? }
.flat_map { |root_dir| Dir.glob(root_dir) }
.map { |root_dir| File.expand_path(root_dir) }
end

def add_related_test_files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,5 +441,48 @@
expect(subject).to eq([[relative_file_path, position_key]])
end
end

context "when models in different root directories share a file basename", :isolated_environment do
let(:options) do
AnnotateRb::Options.new(**include_nothing_options.merge(
{
exclude_tests: false,
root_dir: ["", "packs/*"],
additional_file_patterns: ["packs/*/test/models/%MODEL_NAME_WITHOUT_NS%_test.rb"]
}
))
end

let(:root_test_file) { "test/models/address_test.rb" }
let(:pack_test_file) { "packs/contacts/test/models/address_test.rb" }

before do
FileUtils.mkdir_p("test/models")
FileUtils.touch(root_test_file)

FileUtils.mkdir_p("packs/contacts/test/models")
FileUtils.touch(pack_test_file)
end

context "when the model is in the project root" do
let(:file) { "app/models/address.rb" }
let(:model_name) { "address" }
let(:table_name) { "addresses" }

it "returns only the test file in the project root" do
expect(subject).to eq([[root_test_file, :position_in_test]])
end
end

context "when the model is in a pack" do
let(:file) { "packs/contacts/app/public/models/address.rb" }
let(:model_name) { "contacts/address" }
let(:table_name) { "contact_addresses" }

it "returns only the test file in its own pack" do
expect(subject).to eq([[pack_test_file, :position_in_additional_file_patterns]])
end
end
end
end
end
Loading