1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fix constantize edge case involving prepend, autoloading and name conflicts

In the following situation:

```ruby
class Bar
end

module Baz
end

class Foo
  prepend Baz
end

class Foo::Bar
end
```

Running `Inflector.constantize('Foo::Bar')` would blow up with a NameError.

What is happening is that `constatize` was written before the introduction
of prepend, and wrongly assume that `klass.ancestors.first == klass`.

So it uses `klass.ancestors.inject` without arguments, as a result
a prepended module is used in place of the actual class.
This commit is contained in:
Jean Boussier 2016-12-14 11:47:51 +01:00
parent e3e663f1dc
commit 11e05defec
4 changed files with 16 additions and 1 deletions

View file

@ -274,7 +274,7 @@ module ActiveSupport
# Go down the ancestors to check if it is owned directly. The check
# stops when we reach Object or the end of ancestors tree.
constant = constant.ancestors.inject do |const, ancestor|
constant = constant.ancestors.inject(constant) do |const, ancestor|
break const if ancestor == Object
break ancestor if ancestor.const_defined?(name, false)
const

View file

@ -0,0 +1,8 @@
class SubClassConflict
end
class Prepend
module PrependedModule
end
prepend PrependedModule
end

View file

@ -0,0 +1,2 @@
class Prepend::SubClassConflict
end

View file

@ -73,6 +73,11 @@ module ConstantizeTestCases
yield("RaisesNoMethodError")
end
end
with_autoloading_fixtures do
yield("Prepend::SubClassConflict")
assert_equal "constant", defined?(Prepend::SubClassConflict)
end
end
def run_safe_constantize_tests_on