Closed sattlerc closed 2 years ago
I traced the root cause.
Controllers have optional default helper modules associated with them. For a controller app/controller/stuff_controller.rb
, the Rails framework expects the associated default helper module in app/helper/stuff_helper.rb
.
To handle missing default helper modules, the Rails framework handles MissingSourceFile
exceptions in default_helper_module!
in vendor/rails/actionpack/lib/action_controller/helpers.rb
:
def default_helper_module!
unless name.blank?
module_name = name.sub(/Controller$|$/, 'Helper')
module_path = module_name.split('::').map { |m| m.underscore }.join('/')
require_dependency module_path
helper module_name.constantize
end
rescue MissingSourceFile => e
raise unless e.is_missing? module_path
rescue NameError => e
raise unless e.missing_name? module_name
end
When require_dependency
does not find the specified module, Ruby up until 2.5 raises a MissingSourceFile
exception here. However, in Ruby 2.6, we get a LoadError
.
The call to require_dependency
eventually goes down to a call to the primitive method require
. This would normally raise a LoadError
if an expected file is not found. However, Rails 2 overwrites the new
class method of LoadError
to raise a MissingSourceFile
instead, which is defined as a subclass of LoadError
. This "extension" is defined in vendor/rails/activesupport/lib/active_support/core_ext/load_error.rb
.
The changelog of Ruby 2.6 does not mention any changes in the semantics of exception construction. After digging into the Ruby codebase, I found the responsible commit for this change of behaviour. Built-in exceptions like LoadError
are now directly instantiated without a call to new
(which can be overridden):
error.c: bypass Exception.new
* error.c (rb_exc_new, rb_exc_new_str): instantiate exception
object directly without Exception.new method call.
Redefinition of class method `new` is an outdated style, and
internal exceptions should not be affected by it.
Even after cherry-picking commits from https://github.com/parasew/instiki/ for support of newer Ruby versions, Ruby 2.6 (with any pathc level) fails to load the nLab: