diff options
author | Keenan Brock <keenan@thebrocks.net> | 2019-01-07 14:13:45 -0500 |
---|---|---|
committer | Keenan Brock <keenan@thebrocks.net> | 2019-01-09 14:52:46 -0500 |
commit | a930f5ba0654e8c8c7ac7b3febbb573d03559a40 (patch) | |
tree | eb61061ebddf53c0f41b40b04a563cc9bc664121 | |
parent | 9f1a07af0499080c9fd8815705a03a4c7e8fb506 (diff) | |
download | rails-a930f5ba0654e8c8c7ac7b3febbb573d03559a40.tar.gz rails-a930f5ba0654e8c8c7ac7b3febbb573d03559a40.tar.bz2 rails-a930f5ba0654e8c8c7ac7b3febbb573d03559a40.zip |
Fix safe_constantize to not raise a LoadError.
### Summary
There was an issues when using `safe_constantize` on a string that has
the wrong case.
File `em.rb` defines `EM`.
`"Em".safe_constantize` causes a little confusion with the autoloader.
The autoloader finds file "em.rb",
expecting it to define `Em`, but `Em` is not defined.
The autoloader raises a `LoadError`, which is good,
But `safe_constantize` is defined to return `nil` when a class is not found.
### Before
```
"Em".safe_constantize
LoadError: Unable to autoload constant Em, \
expected rails/activesupport/test/autoloading_fixtures/em.rb to define it
```
### After
```
"Em".safe_constantize
# => nil
```
-rw-r--r-- | activesupport/CHANGELOG.md | 4 | ||||
-rw-r--r-- | activesupport/lib/active_support/inflector/methods.rb | 2 | ||||
-rw-r--r-- | activesupport/test/autoloading_fixtures/raises_load_error.rb | 4 | ||||
-rw-r--r-- | activesupport/test/constantize_test_cases.rb | 10 |
4 files changed, 20 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 360cef2b41..d4eaee9f6d 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,7 @@ +* Fix `String#safe_constantize` throwing a `LoadError` for incorrectly cased constant references. + + *Keenan Brock* + * Preserve key order passed to `ActiveSupport::CacheStore#fetch_multi`. `fetch_multi(*names)` now returns its results in the same order as the `*names` requested, rather than returning cache hits followed by cache misses. diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 1af9833d46..ee193add6f 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -328,6 +328,8 @@ module ActiveSupport e.name.to_s == camel_cased_word.to_s) rescue ArgumentError => e raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message) + rescue LoadError => e + raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(e.message) end # Returns the suffix that should be added to a number to denote the position diff --git a/activesupport/test/autoloading_fixtures/raises_load_error.rb b/activesupport/test/autoloading_fixtures/raises_load_error.rb new file mode 100644 index 0000000000..f97be29b71 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/raises_load_error.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +# raises a load error typical of the dynamic code that manually raises load errors +raise LoadError, "required gem not present kind of error" diff --git a/activesupport/test/constantize_test_cases.rb b/activesupport/test/constantize_test_cases.rb index 2c6145940b..cdb8441b81 100644 --- a/activesupport/test/constantize_test_cases.rb +++ b/activesupport/test/constantize_test_cases.rb @@ -112,6 +112,16 @@ module ConstantizeTestCases assert_nil yield("A::Object::B") assert_nil yield("A::Object::Object::Object::B") + with_autoloading_fixtures do + assert_nil yield("Em") + end + + assert_raises(LoadError) do + with_autoloading_fixtures do + yield("RaisesLoadError") + end + end + assert_raises(NameError) do with_autoloading_fixtures do yield("RaisesNameError") |