I can't entirely tell if this is intended behavior or not. However, here goes:
It appears that load_file in dependencies.rb does not check whether the newly_defined_paths contains constants that cannot be unloaded. It assumes that everything is unloadable and concatenates the results to autoloaded_constants. The autoloaded_constants are then unloaded (during development) after reloading a page.
This issue crops up in a scenario like the following:
a.rb: class A B # just causes missing_constant to load the file for B end
b.rb: class B end
The situation here is that b.rb is contained in a path that has been added to Dependencies.load_once_paths, while a.rb has not. As a result, when load_file is called for a.rb, the newly defined paths will be [A, B].
I have found that adding the following code BEFORE adding anything to the autoloaded_constants ensures that unloadable constants are not unloaded:
... result = nil newly_defined_paths = new_constants_in(*parent_paths) do result = load_without_new_constant_marking path end
# New code starts here... newly_defined_paths.reject! do |new_path| if file_path = search_for_file(new_path.underscore) !loadable_constants_for_path(file_path).include?(new_path) else false end end # And ends here...
autoloaded_constants.concat newly_defined_paths autoloaded_constants.uniq! log "loading #{path} defined #{newly_defined_paths * ', '}" unless newly_defined_paths.empty? return result
This now prevents b.rb from ever being added to autoloaded_constants. I hope that description made sense.
I was wondering if someone from core or with knowledge of the Dependencies system could verify this as an issue or as expected behavior... Thanks!