Skip to content

Commit 508d06a

Browse files
authored
Adding option to skip loading models from subdirectories (#767)
Currently, the models annotator automatically attempts to find a class with a matching name at the bottom of project's directory tree before going up into specific engine's models. This causes issues with models that share names with classes in other engines or lower classes in the project's directory. This PR adds the option to skip attempts to load classes from lower directories and just uses the model's file path directly. #674
1 parent 65dc39f commit 508d06a

File tree

2 files changed

+69
-3
lines changed

2 files changed

+69
-3
lines changed

lib/annotate/annotate_models.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ def root_dir
6767

6868
attr_writer :root_dir
6969

70+
def skip_subdirectory_model_load
71+
# This option is set in options[:skip_subdirectory_model_load]
72+
# and stops the get_loaded_model method from loading a model from a subdir
73+
74+
if @skip_subdirectory_model_load.blank?
75+
false
76+
else
77+
@skip_subdirectory_model_load
78+
end
79+
end
80+
81+
attr_writer :skip_subdirectory_model_load
82+
7083
def get_patterns(options, pattern_types = [])
7184
current_patterns = []
7285
root_dir.each do |root_directory|
@@ -586,8 +599,10 @@ def get_model_class(file)
586599

587600
# Retrieve loaded model class
588601
def get_loaded_model(model_path, file)
589-
loaded_model_class = get_loaded_model_by_path(model_path)
590-
return loaded_model_class if loaded_model_class
602+
unless skip_subdirectory_model_load
603+
loaded_model_class = get_loaded_model_by_path(model_path)
604+
return loaded_model_class if loaded_model_class
605+
end
591606

592607
# We cannot get loaded model when `model_path` is loaded by Rails
593608
# auto_load/eager_load paths. Try all possible model paths one by one.
@@ -616,6 +631,7 @@ def get_loaded_model_by_path(model_path)
616631
def parse_options(options = {})
617632
self.model_dir = split_model_dir(options[:model_dir]) if options[:model_dir]
618633
self.root_dir = options[:root_dir] if options[:root_dir]
634+
self.skip_subdirectory_model_load = options[:skip_subdirectory_model_load].present?
619635
end
620636

621637
def split_model_dir(option_value)

spec/lib/annotate/annotate_models_spec.rb

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ def mock_column(name, type, options = {})
147147
let(:options) do
148148
{
149149
root_dir: '/root',
150-
model_dir: 'app/models,app/one, app/two ,,app/three'
150+
model_dir: 'app/models,app/one, app/two ,,app/three',
151+
skip_subdirectory_model_load: false
151152
}
152153
end
153154

@@ -174,6 +175,40 @@ def mock_column(name, type, options = {})
174175
is_expected.to eq(['app/models', 'app/one', 'app/two', 'app/three'])
175176
end
176177
end
178+
179+
describe '@skip_subdirectory_model_load' do
180+
subject do
181+
AnnotateModels.instance_variable_get(:@skip_subdirectory_model_load)
182+
end
183+
184+
context 'option is set to true' do
185+
let(:options) do
186+
{
187+
root_dir: '/root',
188+
model_dir: 'app/models,app/one, app/two ,,app/three',
189+
skip_subdirectory_model_load: true
190+
}
191+
end
192+
193+
it 'sets skip_subdirectory_model_load to true' do
194+
is_expected.to eq(true)
195+
end
196+
end
197+
198+
context 'option is set to false' do
199+
let(:options) do
200+
{
201+
root_dir: '/root',
202+
model_dir: 'app/models,app/one, app/two ,,app/three',
203+
skip_subdirectory_model_load: false
204+
}
205+
end
206+
207+
it 'sets skip_subdirectory_model_load to false' do
208+
is_expected.to eq(false)
209+
end
210+
end
211+
end
177212
end
178213

179214
describe '.get_schema_info' do
@@ -2087,6 +2122,21 @@ class Bar::Foo
20872122
expect(klass.name).to eq('Foo')
20882123
expect(klass_2.name).to eq('Bar::Foo')
20892124
end
2125+
2126+
it 'attempts to load the model path without expanding if skip_subdirectory_model_load is false' do
2127+
allow(AnnotateModels).to receive(:skip_subdirectory_model_load).and_return(false)
2128+
full_path = File.join(AnnotateModels.model_dir[0], filename_2)
2129+
expect(File).to_not receive(:expand_path).with(full_path)
2130+
AnnotateModels.get_model_class(full_path)
2131+
end
2132+
2133+
it 'does not attempt to load the model path without expanding if skip_subdirectory_model_load is true' do
2134+
$LOAD_PATH.unshift(AnnotateModels.model_dir[0])
2135+
allow(AnnotateModels).to receive(:skip_subdirectory_model_load).and_return(true)
2136+
full_path = File.join(AnnotateModels.model_dir[0], filename_2)
2137+
expect(File).to receive(:expand_path).with(full_path).and_call_original
2138+
AnnotateModels.get_model_class(full_path)
2139+
end
20902140
end
20912141

20922142
context 'one of the classes is nested in another class' do

0 commit comments

Comments
 (0)