Question

Deleting multiple keys in redis-rb

Using redis-rb in a Rails app, the following doesn't work:

irb> keys = $redis.keys("autocomplete*")
=> ["autocomplete_foo", "autocomplete_bar", "autocomplete_bat"]
irb> $redis.del(keys)
=> 0

This works fine:

irb> $redis.del("autocomplete_foo", "autocomplete_bar")
=> 2

Am I missing something obvious? The source is just:

# Delete a key.
def del(*keys)
  synchronize do
    @client.call [:del, *keys]
  end
end

which looks to me like it should work to pass it an array...?

 21  28252  21
1 Jan 1970

Solution

 35

A little coding exploration of the way the splat operator works:

def foo(*keys)
  puts keys.inspect
end

>> foo("hi", "there")
["hi", "there"]

>> foo(["hi", "there"])
[["hi", "there"]]

>> foo(*["hi", "there"])
["hi", "there"]

So passing in a regular array will cause that array to be evaluated as a single item, so that you get an array inside an array within your method. If you preface the array with * when you call the method:

$redis.del(*keys)

That lets the method know to unpack it/not to accept any further arguments. So that should solve the problem that you're having!

Just for the sake of further clarification, this works:

>> foo("hello", *["hi", "there"])

This causes a syntax error:

>> foo("hello", *["hi", "there"], "world")
2011-05-19

Solution

 18

For a Rails app I'm working on, I needed to test the results of loading and unloading redis data.

The namespace is determined by the environment, avoids interacting with development. This worked well.

def clear_redis_cache
  keys = $redis.keys "#{namespace}*"
  $redis.del(*keys) unless keys.empty?
end
2013-11-01