Skip to content

Commit

Permalink
Add safe_constantize to ActiveSupport::Dependencies.
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Nov 23, 2011
1 parent e62de52 commit 0536ea8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 28 deletions.
33 changes: 20 additions & 13 deletions activesupport/lib/active_support/dependencies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ def remove_unloadable_constants!

class ClassCache
def initialize
@store = Hash.new { |h, k| h[k] = Inflector.constantize(k) }
@store = Hash.new
end

def empty?
Expand All @@ -538,23 +538,23 @@ def key?(key)
@store.key?(key)
end

def []=(key, value)
return unless key.respond_to?(:name)

raise(ArgumentError, 'anonymous classes cannot be cached') if key.name.blank?

@store[key.name] = value
def get(key)
key = key.name if key.respond_to?(:name)
@store[key] ||= Inflector.constantize(key)
end

def [](key)
def safe_get(key)
key = key.name if key.respond_to?(:name)

@store[key]
@store[key] || begin
klass = Inflector.safe_constantize(key)
@store[key] = klass
end
end
alias :get :[]

def store(name)
self[name] = name
def store(klass)
return self unless klass.respond_to?(:name)
raise(ArgumentError, 'anonymous classes cannot be cached') if klass.name.empty?
@store[klass.name] = klass
self
end

Expand All @@ -571,10 +571,17 @@ def reference(klass)
end

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

# Get the reference for class named +name+ if one exists.
# Otherwise returns nil.
def safe_constantize(name)
Reference.safe_get(name)
end

# Determine if the given constant has been automatically loaded.
def autoloaded?(desc)
# No name => anonymous module.
Expand Down
38 changes: 23 additions & 15 deletions activesupport/test/class_cache_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,53 @@ def setup

def test_empty?
assert @cache.empty?
@cache[ClassCacheTest] = ClassCacheTest
@cache.store(ClassCacheTest)
assert !@cache.empty?
end

def test_clear!
assert @cache.empty?
@cache[ClassCacheTest] = ClassCacheTest
@cache.store(ClassCacheTest)
assert !@cache.empty?
@cache.clear!
assert @cache.empty?
end

def test_set_key
@cache[ClassCacheTest] = ClassCacheTest
@cache.store(ClassCacheTest)
assert @cache.key?(ClassCacheTest.name)
end

def test_set_rejects_strings
@cache[ClassCacheTest.name] = ClassCacheTest
assert @cache.empty?
end

def test_get_with_class
@cache[ClassCacheTest] = ClassCacheTest
assert_equal ClassCacheTest, @cache[ClassCacheTest]
@cache.store(ClassCacheTest)
assert_equal ClassCacheTest, @cache.get(ClassCacheTest)
end

def test_get_with_name
@cache[ClassCacheTest] = ClassCacheTest
assert_equal ClassCacheTest, @cache[ClassCacheTest.name]
@cache.store(ClassCacheTest)
assert_equal ClassCacheTest, @cache.get(ClassCacheTest.name)
end

def test_get_constantizes
assert @cache.empty?
assert_equal ClassCacheTest, @cache[ClassCacheTest.name]
assert_equal ClassCacheTest, @cache.get(ClassCacheTest.name)
end

def test_get_constantizes_fails_on_invalid_names
assert @cache.empty?
assert_raise NameError do
@cache.get("OmgTotallyInvalidConstantName")
end
end

def test_get_is_an_alias
assert_equal @cache[ClassCacheTest], @cache.get(ClassCacheTest.name)
def test_safe_get_constantizes
assert @cache.empty?
assert_equal ClassCacheTest, @cache.safe_get(ClassCacheTest.name)
end

def test_safe_get_constantizes_doesnt_fail_on_invalid_names
assert @cache.empty?
assert_equal nil, @cache.safe_get("OmgTotallyInvalidConstantName")
end

def test_new_rejects_strings
Expand Down

0 comments on commit 0536ea8

Please sign in to comment.