Annotate gem does not support Rails autoloader collapsed directories
bazay opened this issue · 4 comments
bazay commented
Annotate gem does not support Rails autoloader collapsed directories i.e.
pry(AnnotateModels)> Rails.autoloaders.main
=> #<Zeitwerk::Loader:0x00007f6305898b58
@autoloaded_dirs=[],
@autoloads={},
@collapse_dirs=
#<Set: {"/home/developer/my_app/app/components/my_namespace/models"}>,
@collapse_glob_patterns=#<Set: {/home/developer/my_app/app/components/*/models", "/home/developer/my_app/app/components/my_namespace/jobs"}>,
@eager_load_exclusions=#<Set: {}>,
@eager_loaded=true,
@ignored_glob_patterns=
#<Set: {"/home/developer/my_app/lib/rails",
"/home/developer/my_app/lib/patches",
"//home/developer/my_app/lib/rails/generators/job",
...
pry(AnnotateModels)> Rails.autoloaders.main.collapsed_dirs
=> #<Set: {"/home/developer/my_app/app/components/my_namespace/models"}>
In config/application.rb
:
Rails.autoloaders.main.collapse("app/components/*/models")
I've obfuscated the model names and namespace, but the end result is still the same.
Commands
$ bundle exec annotate
Unable to annotate app/components/my_namespace/models/my_model.rb: file doesn't contain a valid model class
Unable to annotate app/components/my_namespace/models/my_second_model.rb: file doesn't contain a valid model class
Unable to annotate app/components/my_namespace/models/my_third_model.rb: file doesn't contain a valid model class
$
Version
- annotate (3.2.0 96831c1)
- rails (7.0.3.1)
- ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
guigs commented
Here's a monkey patch we are using that find classes based on zeitwerk loader.
Our use case is for loading classes within namespaces. I'm not sure if it works with collapsed dirs, but maybe you can modify it to work.
Put in an initializer:
# frozen_string_literal: true
if Rails.env.development?
require 'annotate'
module AnnotateModelsWithZeitwerk
def get_model_class(file)
loader = Rails.autoloaders.main
root_dirs = loader.dirs(namespaces: true) # or `root_dirs = loader.root_dirs` with zeitwerk < 2.6.1
expanded_file = File.expand_path(file)
root_dir, namespace = root_dirs.find do |dir, _|
expanded_file.start_with?(dir)
end
_, filepath_relative_to_root_dir = expanded_file.split(root_dir)
filepath_relative_to_root_dir = filepath_relative_to_root_dir[1..].sub(/\.rb$/, '')
camelize = loader.inflector.camelize(filepath_relative_to_root_dir, nil)
namespace.const_get(camelize)
end
end
module AnnotateModels
class << self
prepend AnnotateModelsWithZeitwerk
end
end
end