Commit e3e0bbe9 by 0x01f7 Committed by Cuong Tran

Try to get proper loaded model when using Rails eager_load_paths (#535)

parent 9cdf2d34
...@@ -711,11 +711,11 @@ module AnnotateModels ...@@ -711,11 +711,11 @@ module AnnotateModels
model_path = file.gsub(/\.rb$/, '') model_path = file.gsub(/\.rb$/, '')
model_dir.each { |dir| model_path = model_path.gsub(/^#{dir}/, '').gsub(/^\//, '') } model_dir.each { |dir| model_path = model_path.gsub(/^#{dir}/, '').gsub(/^\//, '') }
begin begin
get_loaded_model(model_path) || raise(BadModelFileError.new) get_loaded_model(model_path, file) || raise(BadModelFileError.new)
rescue LoadError rescue LoadError
# this is for non-rails projects, which don't get Rails auto-require magic # this is for non-rails projects, which don't get Rails auto-require magic
file_path = File.expand_path(file) file_path = File.expand_path(file)
if File.file?(file_path) && silence_warnings { Kernel.require(file_path) } if File.file?(file_path) && Kernel.require(file_path)
retry retry
elsif model_path =~ /\// elsif model_path =~ /\//
model_path = model_path.split('/')[1..-1].join('/').to_s model_path = model_path.split('/')[1..-1].join('/').to_s
...@@ -726,8 +726,24 @@ module AnnotateModels ...@@ -726,8 +726,24 @@ module AnnotateModels
end end
end end
# Retrieve loaded model class
def get_loaded_model(model_path, file)
loaded_model_class = get_loaded_model_by_path(model_path)
return loaded_model_class if loaded_model_class
# We cannot get loaded model when `model_path` is loaded by Rails
# auto_load/eager_load paths. Try all possible model paths one by one.
absolute_file = File.expand_path(file)
model_paths =
$LOAD_PATH.select { |path| absolute_file.include?(path) }
.map { |path| absolute_file.sub(path, '').sub(/\.rb$/, '').sub(/^\//, '') }
model_paths
.map { |path| get_loaded_model_by_path(path) }
.find { |loaded_model| !loaded_model.nil? }
end
# Retrieve loaded model class by path to the file where it's supposed to be defined. # Retrieve loaded model class by path to the file where it's supposed to be defined.
def get_loaded_model(model_path) def get_loaded_model_by_path(model_path)
ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.camelize(model_path)) ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.camelize(model_path))
rescue StandardError, LoadError rescue StandardError, LoadError
# Revert to the old way but it is not really robust # Revert to the old way but it is not really robust
...@@ -858,15 +874,6 @@ module AnnotateModels ...@@ -858,15 +874,6 @@ module AnnotateModels
([id] << rest_cols << timestamps << associations).flatten.compact ([id] << rest_cols << timestamps << associations).flatten.compact
end end
# Ignore warnings for the duration of the block ()
def silence_warnings
old_verbose = $VERBOSE
$VERBOSE = nil
yield
ensure
$VERBOSE = old_verbose
end
private private
def with_comments?(klass, options) def with_comments?(klass, options)
......
...@@ -1257,11 +1257,29 @@ EOS ...@@ -1257,11 +1257,29 @@ EOS
EOS EOS
path = File.expand_path('loaded_class', AnnotateModels.model_dir[0]) path = File.expand_path('loaded_class', AnnotateModels.model_dir[0])
Kernel.load "#{path}.rb" Kernel.load "#{path}.rb"
expect(Kernel).not_to receive(:require).with(path) expect(Kernel).not_to receive(:require)
expect(capturing(:stderr) do expect(capturing(:stderr) do
check_class_name 'loaded_class.rb', 'LoadedClass' check_class_name 'loaded_class.rb', 'LoadedClass'
end).not_to include('warning: already initialized constant LoadedClass::CONSTANT') end).to be_blank
end
it 'should not require model files twice which is inside a subdirectory' do
dir = Array.new(8) { (0..9).to_a.sample(random: Random.new) }.join
$LOAD_PATH.unshift(File.join(AnnotateModels.model_dir[0], dir))
create "#{dir}/subdir_loaded_class.rb", <<-EOS
class SubdirLoadedClass < ActiveRecord::Base
CONSTANT = 1
end
EOS
path = File.expand_path("#{dir}/subdir_loaded_class", AnnotateModels.model_dir[0])
Kernel.load "#{path}.rb"
expect(Kernel).not_to receive(:require)
expect(capturing(:stderr) do
check_class_name "#{dir}/subdir_loaded_class.rb", 'SubdirLoadedClass'
end).to be_blank
end end
end end
...@@ -1667,7 +1685,7 @@ end ...@@ -1667,7 +1685,7 @@ end
describe "if a file can't be annotated" do describe "if a file can't be annotated" do
before do before do
allow(AnnotateModels).to receive(:get_loaded_model).with('user').and_return(nil) allow(AnnotateModels).to receive(:get_loaded_model_by_path).with('user').and_return(nil)
write_model('user.rb', <<-EOS) write_model('user.rb', <<-EOS)
class User < ActiveRecord::Base class User < ActiveRecord::Base
...@@ -1697,7 +1715,7 @@ end ...@@ -1697,7 +1715,7 @@ end
describe "if a file can't be deannotated" do describe "if a file can't be deannotated" do
before do before do
allow(AnnotateModels).to receive(:get_loaded_model).with('user').and_return(nil) allow(AnnotateModels).to receive(:get_loaded_model_by_path).with('user').and_return(nil)
write_model('user.rb', <<-EOS) write_model('user.rb', <<-EOS)
class User < ActiveRecord::Base class User < ActiveRecord::Base
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment