Reputation: 437
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...?
Upvotes: 21
Views: 28864
Reputation: 7524
This is better achieved using the enumerator returned by scan_each
.
scan_each(match: 'autocomplete_*').each do |key|
del key
end
This does not load all of the matching keys into memory at once, so it will not be limited by local memory.
Upvotes: 5
Reputation: 18080
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
Upvotes: 18
Reputation: 616
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")
Upvotes: 35