Skip to content

Commit 3257527

Browse files
committed
Make exists variadic.
`exists` now return an Integer if passed multiple keys. If passed a single key it will still return a Boolean, but print a deprecation warning. To get a Boolean use `exists?` instead. To opt-in to the new behavior, set `Redis.exists_returns_integer = true`.
1 parent bf42fc9 commit 3257527

File tree

3 files changed

+68
-7
lines changed

3 files changed

+68
-7
lines changed

lib/redis.rb

+26-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
require_relative "redis/errors"
55

66
class Redis
7+
class << self
8+
attr_accessor :exists_returns_integer
9+
end
10+
711
def self.current
812
@current ||= Redis.new
913
end
@@ -550,13 +554,30 @@ def unlink(*keys)
550554
end
551555
end
552556

553-
# Determine if a key exists.
557+
# Determine how many of the keys exists.
554558
#
555-
# @param [String] key
556-
# @return [Boolean]
557-
def exists(key)
559+
# @param [String, Array<String>] keys
560+
# @return [Integer]
561+
def exists(*keys)
562+
if !Redis.exists_returns_integer && keys.size == 1
563+
message = "`Redis#exists(key)` will return an Integer in redis-rb 4.3, if you want to keep the old behavior, " \
564+
"use `exists?` instead. To opt-in to the new behavior now you can set Redis.exists_returns_integer = true. " \
565+
"(#{::Kernel.caller(1, 1).first})\n"
566+
567+
if defined?(::Warning)
568+
::Warning.warn(message)
569+
else
570+
$stderr.puts(message)
571+
end
572+
exists?(*keys)
573+
else
574+
_exists(*keys)
575+
end
576+
end
577+
578+
def _exists(*keys)
558579
synchronize do |client|
559-
client.call([:exists, key], &Boolify)
580+
client.call([:exists, *keys])
560581
end
561582
end
562583

lib/redis/distributed.rb

+18-2
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,24 @@ def unlink(*args)
171171
end
172172

173173
# Determine if a key exists.
174-
def exists(key)
175-
node_for(key).exists(key)
174+
def exists(*args)
175+
if !Redis.exists_returns_integer && args.size == 1
176+
message = "`Redis#exists(key)` will return an Integer in redis-rb 4.3, if you want to keep the old behavior, " \
177+
"use `exists?` instead. To opt-in to the new behavior now you can set Redis.exists_returns_integer = true. " \
178+
"(#{::Kernel.caller(1, 1).first})\n"
179+
180+
if defined?(::Warning)
181+
::Warning.warn(message)
182+
else
183+
$stderr.puts(message)
184+
end
185+
exists?(*args)
186+
else
187+
keys_per_node = args.group_by { |key| node_for(key) }
188+
keys_per_node.inject(0) do |sum, (node, keys)|
189+
sum + node._exists(*keys)
190+
end
191+
end
176192
end
177193

178194
# Determine if any of the keys exists.

test/lint/value_types.rb

+24
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,30 @@ def test_exists
1111
assert_equal true, r.exists("foo")
1212
end
1313

14+
def test_exists_integer
15+
previous_exists_returns_integer = Redis.exists_returns_integer
16+
Redis.exists_returns_integer = true
17+
assert_equal 0, r.exists("foo")
18+
19+
r.set("foo", "s1")
20+
21+
assert_equal 1, r.exists("foo")
22+
ensure
23+
Redis.exists_returns_integer = previous_exists_returns_integer
24+
end
25+
26+
def test_variadic_exists
27+
assert_equal 0, r.exists("{1}foo", "{1}bar")
28+
29+
r.set("{1}foo", "s1")
30+
31+
assert_equal 1, r.exists("{1}foo", "{1}bar")
32+
33+
r.set("{1}bar", "s2")
34+
35+
assert_equal 2, r.exists("{1}foo", "{1}bar")
36+
end
37+
1438
def test_exists?
1539
assert_equal false, r.exists?("{1}foo", "{1}bar")
1640

0 commit comments

Comments
 (0)