diff options
author | Jean Boussier <jean.boussier@gmail.com> | 2016-12-14 11:47:51 +0100 |
---|---|---|
committer | Jean Boussier <jean.boussier@gmail.com> | 2016-12-14 14:25:43 +0100 |
commit | 11e05defecde965e0eb1929f1b0f1f992be39a6b (patch) | |
tree | 2743c8f2f18edf9aaf4bea170805fe080e216d89 /activesupport | |
parent | e3e663f1dc40a5cfae9ec60e32f5372cd7f9885b (diff) | |
download | rails-11e05defecde965e0eb1929f1b0f1f992be39a6b.tar.gz rails-11e05defecde965e0eb1929f1b0f1f992be39a6b.tar.bz2 rails-11e05defecde965e0eb1929f1b0f1f992be39a6b.zip |
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.
Diffstat (limited to 'activesupport')
4 files changed, 16 insertions, 1 deletions
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index ef3df1240d..fa063af3f4 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -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 diff --git a/activesupport/test/autoloading_fixtures/prepend.rb b/activesupport/test/autoloading_fixtures/prepend.rb new file mode 100644 index 0000000000..3134d1df2b --- /dev/null +++ b/activesupport/test/autoloading_fixtures/prepend.rb @@ -0,0 +1,8 @@ +class SubClassConflict +end + +class Prepend + module PrependedModule + end + prepend PrependedModule +end diff --git a/activesupport/test/autoloading_fixtures/prepend/sub_class_conflict.rb b/activesupport/test/autoloading_fixtures/prepend/sub_class_conflict.rb new file mode 100644 index 0000000000..090dda3043 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/prepend/sub_class_conflict.rb @@ -0,0 +1,2 @@ +class Prepend::SubClassConflict +end diff --git a/activesupport/test/constantize_test_cases.rb b/activesupport/test/constantize_test_cases.rb index af2db8c991..32b720bcbb 100644 --- a/activesupport/test/constantize_test_cases.rb +++ b/activesupport/test/constantize_test_cases.rb @@ -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 |