Skip to content

Commit 5940955

Browse files
authored
Merge pull request rails#48043 from joshuay03/always-raise-on-nil-cache-key
Consistently raise an `ArgumentError` if the `ActiveSupport::Cache` key is blank
2 parents 663df3a + 2b88e78 commit 5940955

File tree

5 files changed

+27
-38
lines changed

5 files changed

+27
-38
lines changed

activesupport/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Consistently raise an `ArgumentError` if the `ActiveSupport::Cache` key is blank.
2+
3+
*Joshua Young*
4+
15
* Deprecate usage of the singleton `ActiveSupport::Deprecation`.
26

37
All usage of `ActiveSupport::Deprecation` as a singleton is deprecated, the most common one being

activesupport/lib/active_support/cache.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -783,10 +783,14 @@ def normalize_options(options)
783783
options
784784
end
785785

786-
# Expands and namespaces the cache key. May be overridden by
787-
# cache stores to do additional normalization.
786+
# Expands and namespaces the cache key.
787+
# Raises an exception when the key is +nil+ or an empty string.
788+
# May be overridden by cache stores to do additional normalization.
788789
def normalize_key(key, options = nil)
789-
namespace_key expanded_key(key), options
790+
str_key = expanded_key(key)
791+
raise(ArgumentError, "key cannot be blank") if !str_key || str_key.empty?
792+
793+
namespace_key str_key, options
790794
end
791795

792796
# Prefix the key with a namespace string:

activesupport/test/cache/behaviors/cache_instrumentation_behavior.rb

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,6 @@ def test_instrumentation_with_fetch_multi_as_super_operation
4242
assert_equal @cache.class.name, events[0].payload[:store]
4343
end
4444

45-
def test_instrumentation_empty_fetch_multi
46-
events = with_instrumentation "read_multi" do
47-
@cache.fetch_multi() { |key| key * 2 }
48-
end
49-
50-
assert_equal %w[ cache_read_multi.active_support ], events.map(&:name)
51-
assert_equal :fetch_multi, events[0].payload[:super_operation]
52-
assert_equal [], events[0].payload[:key]
53-
assert_equal [], events[0].payload[:hits]
54-
assert_equal @cache.class.name, events[0].payload[:store]
55-
end
56-
5745
def test_read_multi_instrumentation
5846
key_1 = SecureRandom.uuid
5947
@cache.write(key_1, SecureRandom.alphanumeric)
@@ -70,17 +58,6 @@ def test_read_multi_instrumentation
7058
assert_equal @cache.class.name, events[0].payload[:store]
7159
end
7260

73-
def test_empty_read_multi_instrumentation
74-
events = with_instrumentation "read_multi" do
75-
@cache.read_multi()
76-
end
77-
78-
assert_equal %w[ cache_read_multi.active_support ], events.map(&:name)
79-
assert_equal [], events[0].payload[:key]
80-
assert_equal [], events[0].payload[:hits]
81-
assert_equal @cache.class.name, events[0].payload[:store]
82-
end
83-
8461
private
8562
def with_instrumentation(method)
8663
event_name = "cache_#{method}.active_support"

activesupport/test/cache/behaviors/cache_store_behavior.rb

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,6 @@ def test_read_multi_with_expires
159159
end
160160
end
161161

162-
def test_read_multi_with_empty_keys_and_a_logger_and_no_namespace
163-
cache = lookup_store(namespace: nil)
164-
cache.logger = ActiveSupport::Logger.new(nil)
165-
assert_equal({}, cache.read_multi)
166-
end
167-
168162
def test_fetch_multi
169163
key = SecureRandom.uuid
170164
other_key = SecureRandom.uuid
@@ -464,6 +458,22 @@ def test_keys_are_case_sensitive
464458
assert_nil @cache.read(key.upcase)
465459
end
466460

461+
def test_blank_key
462+
invalid_keys = [nil, "", [], {}]
463+
invalid_keys.each do |key|
464+
assert_raises(ArgumentError) { @cache.write(key, "bar") }
465+
assert_raises(ArgumentError) { @cache.read(key) }
466+
assert_raises(ArgumentError) { @cache.delete(key) }
467+
end
468+
469+
valid_keys = ["foo", ["bar"], { foo: "bar" }, 0, 1, InstanceTest.new("foo", 2)]
470+
valid_keys.each do |key|
471+
assert_nothing_raised { @cache.write(key, "bar") }
472+
assert_nothing_raised { @cache.read(key) }
473+
assert_nothing_raised { @cache.delete(key) }
474+
end
475+
end
476+
467477
def test_exist
468478
key = SecureRandom.alphanumeric
469479
@cache.write(key, "bar")

activesupport/test/cache/stores/redis_cache_store_test.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,6 @@ def test_fetch_multi_with_namespace
164164
end
165165
end
166166

167-
def test_fetch_multi_without_names
168-
assert_not_called(@cache.redis, :mget) do
169-
@cache.fetch_multi() { }
170-
end
171-
end
172-
173167
def test_write_expires_at
174168
@cache.write "key_with_expires_at", "bar", expires_at: 30.minutes.from_now
175169
assert @cache.redis.ttl("#{@namespace}:key_with_expires_at") > 0

0 commit comments

Comments
 (0)