Skip to content

Commit 0536ea8

Browse files
committed
Add safe_constantize to ActiveSupport::Dependencies.
1 parent e62de52 commit 0536ea8

File tree

2 files changed

+43
-28
lines changed

2 files changed

+43
-28
lines changed

activesupport/lib/active_support/dependencies.rb

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ def remove_unloadable_constants!
527527

528528
class ClassCache
529529
def initialize
530-
@store = Hash.new { |h, k| h[k] = Inflector.constantize(k) }
530+
@store = Hash.new
531531
end
532532

533533
def empty?
@@ -538,23 +538,23 @@ def key?(key)
538538
@store.key?(key)
539539
end
540540

541-
def []=(key, value)
542-
return unless key.respond_to?(:name)
543-
544-
raise(ArgumentError, 'anonymous classes cannot be cached') if key.name.blank?
545-
546-
@store[key.name] = value
541+
def get(key)
542+
key = key.name if key.respond_to?(:name)
543+
@store[key] ||= Inflector.constantize(key)
547544
end
548545

549-
def [](key)
546+
def safe_get(key)
550547
key = key.name if key.respond_to?(:name)
551-
552-
@store[key]
548+
@store[key] || begin
549+
klass = Inflector.safe_constantize(key)
550+
@store[key] = klass
551+
end
553552
end
554-
alias :get :[]
555553

556-
def store(name)
557-
self[name] = name
554+
def store(klass)
555+
return self unless klass.respond_to?(:name)
556+
raise(ArgumentError, 'anonymous classes cannot be cached') if klass.name.empty?
557+
@store[klass.name] = klass
558558
self
559559
end
560560

@@ -571,10 +571,17 @@ def reference(klass)
571571
end
572572

573573
# Get the reference for class named +name+.
574+
# Raises an exception if referenced class does not exist.
574575
def constantize(name)
575576
Reference.get(name)
576577
end
577578

579+
# Get the reference for class named +name+ if one exists.
580+
# Otherwise returns nil.
581+
def safe_constantize(name)
582+
Reference.safe_get(name)
583+
end
584+
578585
# Determine if the given constant has been automatically loaded.
579586
def autoloaded?(desc)
580587
# No name => anonymous module.

activesupport/test/class_cache_test.rb

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,53 @@ def setup
1010

1111
def test_empty?
1212
assert @cache.empty?
13-
@cache[ClassCacheTest] = ClassCacheTest
13+
@cache.store(ClassCacheTest)
1414
assert !@cache.empty?
1515
end
1616

1717
def test_clear!
1818
assert @cache.empty?
19-
@cache[ClassCacheTest] = ClassCacheTest
19+
@cache.store(ClassCacheTest)
2020
assert !@cache.empty?
2121
@cache.clear!
2222
assert @cache.empty?
2323
end
2424

2525
def test_set_key
26-
@cache[ClassCacheTest] = ClassCacheTest
26+
@cache.store(ClassCacheTest)
2727
assert @cache.key?(ClassCacheTest.name)
2828
end
2929

30-
def test_set_rejects_strings
31-
@cache[ClassCacheTest.name] = ClassCacheTest
32-
assert @cache.empty?
33-
end
34-
3530
def test_get_with_class
36-
@cache[ClassCacheTest] = ClassCacheTest
37-
assert_equal ClassCacheTest, @cache[ClassCacheTest]
31+
@cache.store(ClassCacheTest)
32+
assert_equal ClassCacheTest, @cache.get(ClassCacheTest)
3833
end
3934

4035
def test_get_with_name
41-
@cache[ClassCacheTest] = ClassCacheTest
42-
assert_equal ClassCacheTest, @cache[ClassCacheTest.name]
36+
@cache.store(ClassCacheTest)
37+
assert_equal ClassCacheTest, @cache.get(ClassCacheTest.name)
4338
end
4439

4540
def test_get_constantizes
4641
assert @cache.empty?
47-
assert_equal ClassCacheTest, @cache[ClassCacheTest.name]
42+
assert_equal ClassCacheTest, @cache.get(ClassCacheTest.name)
43+
end
44+
45+
def test_get_constantizes_fails_on_invalid_names
46+
assert @cache.empty?
47+
assert_raise NameError do
48+
@cache.get("OmgTotallyInvalidConstantName")
49+
end
4850
end
4951

50-
def test_get_is_an_alias
51-
assert_equal @cache[ClassCacheTest], @cache.get(ClassCacheTest.name)
52+
def test_safe_get_constantizes
53+
assert @cache.empty?
54+
assert_equal ClassCacheTest, @cache.safe_get(ClassCacheTest.name)
55+
end
56+
57+
def test_safe_get_constantizes_doesnt_fail_on_invalid_names
58+
assert @cache.empty?
59+
assert_equal nil, @cache.safe_get("OmgTotallyInvalidConstantName")
5260
end
5361

5462
def test_new_rejects_strings

0 commit comments

Comments
 (0)