Skip to content

Commit f5ec74c

Browse files
authored
Evaluate Proc namespaces every time (not just at initialization) (#923)
When creating a dalli client with a Proc for the namespace option, it would generally mean that the namespace may change from operation to operation. Saving the result of calling the proc in the KeyManager instance at initialisation time means that the client will always use the value of the namespace as it was when the client was created. If this was the desired behaviour, it would be just as easy to pass that value as a string instead of a Proc.
1 parent 903295c commit f5ec74c

2 files changed

Lines changed: 35 additions & 6 deletions

File tree

lib/dalli/key_manager.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def validate_key(key)
6161
def key_with_namespace(key)
6262
return key if namespace.nil?
6363

64-
"#{namespace}#{NAMESPACE_SEPARATOR}#{key}"
64+
"#{evaluate_namespace}#{NAMESPACE_SEPARATOR}#{key}"
6565
end
6666

6767
def key_without_namespace(key)
@@ -75,6 +75,8 @@ def digest_class
7575
end
7676

7777
def namespace_regexp
78+
return /\A#{Regexp.escape(evaluate_namespace)}:/ if namespace.is_a?(Proc)
79+
7880
@namespace_regexp ||= /\A#{Regexp.escape(namespace)}:/.freeze unless namespace.nil?
7981
end
8082

@@ -87,9 +89,15 @@ def validate_digest_class_option(opts)
8789
def namespace_from_options
8890
raw_namespace = @key_options[:namespace]
8991
return nil unless raw_namespace
90-
return raw_namespace.call.to_s if raw_namespace.is_a?(Proc)
92+
return raw_namespace.to_s unless raw_namespace.is_a?(Proc)
93+
94+
raw_namespace
95+
end
96+
97+
def evaluate_namespace
98+
return namespace.call.to_s if namespace.is_a?(Proc)
9199

92-
raw_namespace.to_s
100+
namespace
93101
end
94102

95103
##

test/test_key_manager.rb

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,34 @@
6666
end
6767

6868
describe 'when there is a Proc provided as a namespace parameter' do
69-
let(:options) { { namespace: namespace_as_symbol } }
69+
let(:options) { { namespace: namespace_as_proc } }
7070
let(:namespace_as_proc) { proc { namespace_as_symbol } }
7171
let(:namespace_as_symbol) { namespace_as_s.to_sym }
7272
let(:namespace_as_s) { SecureRandom.hex(5) }
7373

74-
it 'the namespace is the stringified symbol' do
75-
assert_equal namespace_as_s, key_manager.namespace
74+
it 'the namespace is the proc' do
75+
assert_equal namespace_as_proc, key_manager.namespace
76+
end
77+
78+
it 'the evaluated namespace is the stringified symbol' do
79+
assert_equal namespace_as_s, key_manager.evaluate_namespace
80+
end
81+
end
82+
83+
describe 'when the namespace Proc returns dynamic results' do
84+
count = 0
85+
86+
let(:options) { { namespace: namespace_as_proc } }
87+
let(:namespace_as_proc) do
88+
proc { count += 1 }
89+
end
90+
91+
it 'evaluates the namespace proc every time we need it' do
92+
assert_equal 0, count
93+
assert_equal '1', key_manager.evaluate_namespace
94+
assert_equal(/\A2:/, key_manager.namespace_regexp)
95+
assert_equal '3', key_manager.evaluate_namespace
96+
assert_equal '4:test', key_manager.key_with_namespace('test')
7697
end
7798
end
7899
end

0 commit comments

Comments
 (0)