redis-namespace 1.5.2 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +17 -16
- data/README.md +85 -20
- data/lib/redis/namespace.rb +155 -45
- data/lib/redis/namespace/version.rb +1 -1
- data/spec/deprecation_spec.rb +34 -2
- data/spec/redis_spec.rb +316 -180
- data/spec/spec_helper.rb +5 -0
- metadata +45 -46
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 781a6361b78e31842c9fe934161b83e1acf9d1c1ef50cd015694b78582b461ac
|
4
|
+
data.tar.gz: a0856e98fb69b1063c460ef1479dd57a4659741612b398d3fac2d4bb3727e1b0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: caf163b05d1f4c5f08a29d4d1f977d666f1a627b582af762f50d883df64f0f2139fe132918edbc6c59d9259f386f7ed7a094da3493579072f25d9c957da7e7eb
|
7
|
+
data.tar.gz: 951f20c3aaedd77400f34b161fb642d39ff0a4e8a619506441288f6671043a3bfd3e1f18e13a62fc8e014f79d989246fcb51b351f4d3f1b6f3a2a6ce8f17bd41
|
data/LICENSE
CHANGED
@@ -1,20 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
1
3
|
Copyright (c) 2009 Chris Wanstrath
|
2
4
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
the following conditions:
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
10
11
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
13
14
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
OF
|
20
|
-
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,38 +1,103 @@
|
|
1
1
|
redis-namespace
|
2
|
-
|
2
|
+
===============
|
3
|
+
|
4
|
+
Redis::Namespace provides an interface to a namespaced subset of your [redis][] keyspace (e.g., keys with a common beginning), and requires the [redis-rb][] gem.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
require 'redis-namespace'
|
8
|
+
# => true
|
9
|
+
|
10
|
+
redis_connection = Redis.new
|
11
|
+
# => #<Redis client v3.1.0 for redis://127.0.0.1:6379/0>
|
12
|
+
namespaced_redis = Redis::Namespace.new(:ns, redis: redis_connection)
|
13
|
+
# => #<Redis::Namespace v1.5.0 with client v3.1.0 for redis://127.0.0.1:6379/0/ns>
|
14
|
+
|
15
|
+
namespaced_redis.set('foo', 'bar') # redis_connection.set('ns:foo', 'bar')
|
16
|
+
# => "OK"
|
17
|
+
|
18
|
+
# Redis::Namespace automatically prepended our namespace to the key
|
19
|
+
# before sending it to our redis client.
|
20
|
+
|
21
|
+
namespaced_redis.get('foo')
|
22
|
+
# => "bar"
|
23
|
+
redis_connection.get('foo')
|
24
|
+
# => nil
|
25
|
+
redis_connection.get('ns:foo')
|
26
|
+
# => "bar"
|
27
|
+
|
28
|
+
namespaced_redis.del('foo')
|
29
|
+
# => 1
|
30
|
+
namespaced_redis.get('foo')
|
31
|
+
# => nil
|
32
|
+
redis_connection.get('ns:foo')
|
33
|
+
# => nil
|
34
|
+
```
|
3
35
|
|
4
|
-
|
36
|
+
Installation
|
37
|
+
============
|
5
38
|
|
6
|
-
|
39
|
+
Redis::Namespace is packaged as the redis-namespace gem, and hosted on rubygems.org.
|
7
40
|
|
8
|
-
|
9
|
-
|
10
|
-
|
41
|
+
From the command line:
|
42
|
+
|
43
|
+
$ gem install redis-namespace
|
44
|
+
|
45
|
+
Or in your Gemfile:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
gem 'redis-namespace'
|
11
49
|
```
|
12
50
|
|
13
|
-
|
51
|
+
Caveats
|
52
|
+
=======
|
14
53
|
|
15
|
-
|
54
|
+
`Redis::Namespace` provides a namespaced interface to `Redis` by keeping an internal registry of the method signatures in `Redis` provided by the [redis-rb][] gem; we keep track of which arguments need the namespace added, and which return values need the namespace removed.
|
16
55
|
|
17
|
-
|
56
|
+
Blind Passthrough
|
57
|
+
-----------------
|
58
|
+
If your version of this gem doesn't know about a particular command, it can't namespace it. Historically, this has meant that Redis::Namespace blindly passes unknown commands on to the underlying redis connection without modification which can lead to surprising effects.
|
18
59
|
|
60
|
+
As of v1.5.0, blind passthrough has been deprecated, and the functionality will be removed entirely in 2.0.
|
19
61
|
|
20
|
-
|
21
|
-
============
|
62
|
+
If you come across a command that is not yet supported, please open an issue on the [issue tracker][] or submit a pull-request.
|
22
63
|
|
23
|
-
|
64
|
+
Administrative Commands
|
65
|
+
-----------------------
|
66
|
+
The effects of some redis commands cannot be limited to a particular namespace (e.g., `FLUSHALL`, which literally truncates all databases in your redis server, regardless of keyspace). Historically, this has meant that Redis::Namespace intentionally passes administrative commands on to the underlying redis connection without modification, which can lead to surprising effects.
|
24
67
|
|
68
|
+
As of v1.6.0, the direct use of administrative commands has been deprecated, and the functionality will be removed entirely in 2.0; while such commands are often useful for testing or administration, their meaning is inherently hidden when placed behind an interface that implies it will namespace everything.
|
25
69
|
|
70
|
+
The prefered way to send an administrative command is on the redis connection itself, which is publicly exposed as `Redis::Namespace#redis`:
|
26
71
|
|
27
|
-
|
28
|
-
|
72
|
+
```ruby
|
73
|
+
namespaced.redis.flushall()
|
74
|
+
# => "OK"
|
75
|
+
```
|
76
|
+
|
77
|
+
2.x Planned Breaking Changes
|
78
|
+
============================
|
29
79
|
|
30
|
-
|
31
|
-
|
80
|
+
As mentioned above, 2.0 will remove blind passthrough and the administrative command passthrough.
|
81
|
+
By default in 1.5+, deprecation warnings are present and enabled;
|
82
|
+
they can be silenced by initializing `Redis::Namespace` with `warnings: false` or by setting the `REDIS_NAMESPACE_QUIET` environment variable.
|
83
|
+
|
84
|
+
Early opt-in
|
85
|
+
------------
|
86
|
+
|
87
|
+
To enable testing against the 2.x interface before its release, in addition to deprecation warnings, early opt-in to these changes can be enabled by initializing `Redis::Namespace` with `deprecations: true` or by setting the `REDIS_NAMESPACE_DEPRECATIONS` environment variable.
|
88
|
+
This should only be done once all warnings have been addressed.
|
89
|
+
|
90
|
+
Authors
|
91
|
+
=======
|
32
92
|
|
93
|
+
While there are many authors who have contributed to this project, the following have done so on an ongoing basis with at least 5 commits:
|
33
94
|
|
34
|
-
|
35
|
-
|
95
|
+
- Chris Wanstrath (@defunkt)
|
96
|
+
- Ryan Biesemeyer (@yaauie)
|
97
|
+
- Steve Klabnik (@steveklabnik)
|
98
|
+
- Terence Lee (@hone)
|
99
|
+
- Eoin Coffey (@ecoffey)
|
36
100
|
|
37
|
-
|
38
|
-
|
101
|
+
[redis]: http://redis.io
|
102
|
+
[redis-rb]: https://github.com/redis/redis-rb
|
103
|
+
[issue tracker]: https://github.com/resque/redis-namespace/issues
|
data/lib/redis/namespace.rb
CHANGED
@@ -3,7 +3,7 @@ require 'redis/namespace/version'
|
|
3
3
|
|
4
4
|
class Redis
|
5
5
|
class Namespace
|
6
|
-
# The following
|
6
|
+
# The following tables define how input parameters and result
|
7
7
|
# values should be modified for the namespace.
|
8
8
|
#
|
9
9
|
# COMMANDS is a hash. Each key is the name of a command and each
|
@@ -53,34 +53,27 @@ class Redis
|
|
53
53
|
# :all
|
54
54
|
# Add the namespace to all elements returned, e.g.
|
55
55
|
# key1 key2 => namespace:key1 namespace:key2
|
56
|
-
|
57
|
-
"append" => [:first],
|
58
|
-
"auth" => [],
|
59
|
-
"bgrewriteaof" => [],
|
60
|
-
"bgsave" => [],
|
56
|
+
NAMESPACED_COMMANDS = {
|
57
|
+
"append" => [ :first ],
|
61
58
|
"bitcount" => [ :first ],
|
62
59
|
"bitop" => [ :exclude_first ],
|
60
|
+
"bitpos" => [ :first ],
|
63
61
|
"blpop" => [ :exclude_last, :first ],
|
64
62
|
"brpop" => [ :exclude_last, :first ],
|
65
63
|
"brpoplpush" => [ :exclude_last ],
|
66
|
-
"
|
67
|
-
"
|
64
|
+
"bzpopmin" => [ :first ],
|
65
|
+
"bzpopmax" => [ :first ],
|
68
66
|
"debug" => [ :exclude_first ],
|
69
67
|
"decr" => [ :first ],
|
70
68
|
"decrby" => [ :first ],
|
71
69
|
"del" => [ :all ],
|
72
|
-
"discard" => [],
|
73
|
-
"disconnect!" => [],
|
74
70
|
"dump" => [ :first ],
|
75
|
-
"
|
76
|
-
"exists"
|
71
|
+
"exists" => [ :all ],
|
72
|
+
"exists?" => [ :all ],
|
77
73
|
"expire" => [ :first ],
|
78
74
|
"expireat" => [ :first ],
|
79
75
|
"eval" => [ :eval_style ],
|
80
76
|
"evalsha" => [ :eval_style ],
|
81
|
-
"exec" => [],
|
82
|
-
"flushall" => [],
|
83
|
-
"flushdb" => [],
|
84
77
|
"get" => [ :first ],
|
85
78
|
"getbit" => [ :first ],
|
86
79
|
"getrange" => [ :first ],
|
@@ -103,9 +96,7 @@ class Redis
|
|
103
96
|
"incr" => [ :first ],
|
104
97
|
"incrby" => [ :first ],
|
105
98
|
"incrbyfloat" => [ :first ],
|
106
|
-
"info" => [],
|
107
99
|
"keys" => [ :first, :all ],
|
108
|
-
"lastsave" => [],
|
109
100
|
"lindex" => [ :first ],
|
110
101
|
"linsert" => [ :first ],
|
111
102
|
"llen" => [ :first ],
|
@@ -124,7 +115,6 @@ class Redis
|
|
124
115
|
"mget" => [ :all ],
|
125
116
|
"monitor" => [ :monitor ],
|
126
117
|
"move" => [ :first ],
|
127
|
-
"multi" => [],
|
128
118
|
"mset" => [ :alternate ],
|
129
119
|
"msetnx" => [ :alternate ],
|
130
120
|
"object" => [ :exclude_first ],
|
@@ -134,14 +124,11 @@ class Redis
|
|
134
124
|
"pfadd" => [ :first ],
|
135
125
|
"pfcount" => [ :all ],
|
136
126
|
"pfmerge" => [ :all ],
|
137
|
-
"ping" => [],
|
138
127
|
"psetex" => [ :first ],
|
139
128
|
"psubscribe" => [ :all ],
|
140
129
|
"pttl" => [ :first ],
|
141
130
|
"publish" => [ :first ],
|
142
131
|
"punsubscribe" => [ :all ],
|
143
|
-
"quit" => [],
|
144
|
-
"randomkey" => [],
|
145
132
|
"rename" => [ :all ],
|
146
133
|
"renamenx" => [ :all ],
|
147
134
|
"restore" => [ :first ],
|
@@ -150,24 +137,19 @@ class Redis
|
|
150
137
|
"rpush" => [ :first ],
|
151
138
|
"rpushx" => [ :first ],
|
152
139
|
"sadd" => [ :first ],
|
153
|
-
"save" => [],
|
154
140
|
"scard" => [ :first ],
|
155
141
|
"scan" => [ :scan_style, :second ],
|
156
142
|
"scan_each" => [ :scan_style, :all ],
|
157
|
-
"script" => [],
|
158
143
|
"sdiff" => [ :all ],
|
159
144
|
"sdiffstore" => [ :all ],
|
160
|
-
"select" => [],
|
161
145
|
"set" => [ :first ],
|
162
146
|
"setbit" => [ :first ],
|
163
147
|
"setex" => [ :first ],
|
164
148
|
"setnx" => [ :first ],
|
165
149
|
"setrange" => [ :first ],
|
166
|
-
"shutdown" => [],
|
167
150
|
"sinter" => [ :all ],
|
168
151
|
"sinterstore" => [ :all ],
|
169
152
|
"sismember" => [ :first ],
|
170
|
-
"slaveof" => [],
|
171
153
|
"smembers" => [ :first ],
|
172
154
|
"smove" => [ :exclude_last ],
|
173
155
|
"sort" => [ :sort ],
|
@@ -182,31 +164,75 @@ class Redis
|
|
182
164
|
"sunionstore" => [ :all ],
|
183
165
|
"ttl" => [ :first ],
|
184
166
|
"type" => [ :first ],
|
167
|
+
"unlink" => [ :all ],
|
185
168
|
"unsubscribe" => [ :all ],
|
186
|
-
"unwatch" => [ :all ],
|
187
|
-
"watch" => [ :all ],
|
188
169
|
"zadd" => [ :first ],
|
189
170
|
"zcard" => [ :first ],
|
190
171
|
"zcount" => [ :first ],
|
191
172
|
"zincrby" => [ :first ],
|
192
173
|
"zinterstore" => [ :exclude_options ],
|
174
|
+
"zpopmin" => [ :first ],
|
175
|
+
"zpopmax" => [ :first ],
|
193
176
|
"zrange" => [ :first ],
|
194
177
|
"zrangebyscore" => [ :first ],
|
178
|
+
"zrangebylex" => [ :first ],
|
195
179
|
"zrank" => [ :first ],
|
196
180
|
"zrem" => [ :first ],
|
197
181
|
"zremrangebyrank" => [ :first ],
|
198
182
|
"zremrangebyscore" => [ :first ],
|
183
|
+
"zremrangebylex" => [ :first ],
|
199
184
|
"zrevrange" => [ :first ],
|
200
185
|
"zrevrangebyscore" => [ :first ],
|
186
|
+
"zrevrangebylex" => [ :first ],
|
201
187
|
"zrevrank" => [ :first ],
|
202
188
|
"zscan" => [ :first ],
|
203
189
|
"zscan_each" => [ :first ],
|
204
190
|
"zscore" => [ :first ],
|
205
|
-
"zunionstore" => [ :exclude_options ]
|
206
|
-
|
207
|
-
|
191
|
+
"zunionstore" => [ :exclude_options ]
|
192
|
+
}
|
193
|
+
TRANSACTION_COMMANDS = {
|
194
|
+
"discard" => [],
|
195
|
+
"exec" => [],
|
196
|
+
"multi" => [],
|
197
|
+
"unwatch" => [ :all ],
|
198
|
+
"watch" => [ :all ],
|
199
|
+
}
|
200
|
+
HELPER_COMMANDS = {
|
201
|
+
"auth" => [],
|
202
|
+
"disconnect!" => [],
|
203
|
+
"echo" => [],
|
204
|
+
"ping" => [],
|
205
|
+
"time" => [],
|
206
|
+
}
|
207
|
+
ADMINISTRATIVE_COMMANDS = {
|
208
|
+
"bgrewriteaof" => [],
|
209
|
+
"bgsave" => [],
|
210
|
+
"config" => [],
|
211
|
+
"dbsize" => [],
|
212
|
+
"flushall" => [],
|
213
|
+
"flushdb" => [],
|
214
|
+
"info" => [],
|
215
|
+
"lastsave" => [],
|
216
|
+
"quit" => [],
|
217
|
+
"randomkey" => [],
|
218
|
+
"save" => [],
|
219
|
+
"script" => [],
|
220
|
+
"select" => [],
|
221
|
+
"shutdown" => [],
|
222
|
+
"slaveof" => [],
|
208
223
|
}
|
209
224
|
|
225
|
+
DEPRECATED_COMMANDS = [
|
226
|
+
ADMINISTRATIVE_COMMANDS
|
227
|
+
].compact.reduce(:merge)
|
228
|
+
|
229
|
+
COMMANDS = [
|
230
|
+
NAMESPACED_COMMANDS,
|
231
|
+
TRANSACTION_COMMANDS,
|
232
|
+
HELPER_COMMANDS,
|
233
|
+
ADMINISTRATIVE_COMMANDS,
|
234
|
+
].compact.reduce(:merge)
|
235
|
+
|
210
236
|
# Support 1.8.7 by providing a namespaced reference to Enumerable::Enumerator
|
211
237
|
Enumerator = Enumerable::Enumerator unless defined?(::Enumerator)
|
212
238
|
|
@@ -223,6 +249,7 @@ class Redis
|
|
223
249
|
@deprecations = !!options.fetch(:deprecations) do
|
224
250
|
ENV['REDIS_NAMESPACE_DEPRECATIONS']
|
225
251
|
end
|
252
|
+
@has_new_client_method = @redis.respond_to?(:_client)
|
226
253
|
end
|
227
254
|
|
228
255
|
def deprecations?
|
@@ -234,7 +261,13 @@ class Redis
|
|
234
261
|
end
|
235
262
|
|
236
263
|
def client
|
237
|
-
|
264
|
+
warn("The client method is deprecated as of redis-rb 4.0.0, please use the new _client" +
|
265
|
+
"method instead. Support for the old method will be removed in redis-namespace 2.0.") if @has_new_client_method && deprecations?
|
266
|
+
_client
|
267
|
+
end
|
268
|
+
|
269
|
+
def _client
|
270
|
+
@has_new_client_method ? @redis._client : @redis.client # for redis-4.0.0
|
238
271
|
end
|
239
272
|
|
240
273
|
# Ruby defines a now deprecated type method so we need to override it here
|
@@ -247,7 +280,9 @@ class Redis
|
|
247
280
|
|
248
281
|
# emulate Ruby 1.9+ and keep respond_to_missing? logic together.
|
249
282
|
def respond_to?(command, include_private=false)
|
250
|
-
|
283
|
+
return !deprecations? if DEPRECATED_COMMANDS.include?(command.to_s.downcase)
|
284
|
+
|
285
|
+
respond_to_missing?(command, include_private) or super
|
251
286
|
end
|
252
287
|
|
253
288
|
def keys(query = nil)
|
@@ -275,6 +310,14 @@ class Redis
|
|
275
310
|
@namespace
|
276
311
|
end
|
277
312
|
|
313
|
+
def full_namespace
|
314
|
+
redis.is_a?(Namespace) ? "#{redis.full_namespace}:#{namespace}" : namespace.to_s
|
315
|
+
end
|
316
|
+
|
317
|
+
def connection
|
318
|
+
@redis.connection.tap { |info| info[:namespace] = @namespace }
|
319
|
+
end
|
320
|
+
|
278
321
|
def exec
|
279
322
|
call_with_namespace(:exec)
|
280
323
|
end
|
@@ -282,19 +325,46 @@ class Redis
|
|
282
325
|
def eval(*args)
|
283
326
|
call_with_namespace(:eval, *args)
|
284
327
|
end
|
328
|
+
ruby2_keywords(:eval) if respond_to?(:ruby2_keywords, true)
|
329
|
+
|
330
|
+
ADMINISTRATIVE_COMMANDS.keys.each do |command|
|
331
|
+
define_method(command) do |*args, &block|
|
332
|
+
raise NoMethodError if deprecations?
|
333
|
+
|
334
|
+
if warning?
|
335
|
+
warn("Passing '#{command}' command to redis as is; " +
|
336
|
+
"administrative commands cannot be effectively namespaced " +
|
337
|
+
"and should be called on the redis connection directly; " +
|
338
|
+
"passthrough has been deprecated and will be removed in " +
|
339
|
+
"redis-namespace 2.0 (at #{call_site})"
|
340
|
+
)
|
341
|
+
end
|
342
|
+
call_with_namespace(command, *args, &block)
|
343
|
+
end
|
344
|
+
ruby2_keywords(command) if respond_to?(:ruby2_keywords, true)
|
345
|
+
end
|
346
|
+
|
347
|
+
COMMANDS.keys.each do |command|
|
348
|
+
next if ADMINISTRATIVE_COMMANDS.include?(command)
|
349
|
+
next if method_defined?(command)
|
350
|
+
|
351
|
+
define_method(command) do |*args, &block|
|
352
|
+
call_with_namespace(command, *args, &block)
|
353
|
+
end
|
354
|
+
ruby2_keywords(command) if respond_to?(:ruby2_keywords, true)
|
355
|
+
end
|
285
356
|
|
286
357
|
def method_missing(command, *args, &block)
|
287
358
|
normalized_command = command.to_s.downcase
|
288
359
|
|
289
360
|
if COMMANDS.include?(normalized_command)
|
290
|
-
|
361
|
+
send(normalized_command, *args, &block)
|
291
362
|
elsif @redis.respond_to?(normalized_command) && !deprecations?
|
292
363
|
# blind passthrough is deprecated and will be removed in 2.0
|
293
364
|
# redis-namespace does not know how to handle this command.
|
294
365
|
# Passing it to @redis as is, where redis-namespace shows
|
295
366
|
# a warning message if @warning is set.
|
296
367
|
if warning?
|
297
|
-
call_site = caller.reject { |l| l.start_with?(__FILE__) }.first
|
298
368
|
warn("Passing '#{command}' command to redis as is; blind " +
|
299
369
|
"passthrough has been deprecated and will be removed in " +
|
300
370
|
"redis-namespace 2.0 (at #{call_site})")
|
@@ -304,16 +374,24 @@ class Redis
|
|
304
374
|
super
|
305
375
|
end
|
306
376
|
end
|
377
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
378
|
+
|
379
|
+
def inspect
|
380
|
+
"<#{self.class.name} v#{VERSION} with client v#{Redis::VERSION} "\
|
381
|
+
"for #{@redis.id}/#{full_namespace}>"
|
382
|
+
end
|
307
383
|
|
308
384
|
def respond_to_missing?(command, include_all=false)
|
309
|
-
|
385
|
+
normalized_command = command.to_s.downcase
|
310
386
|
|
311
|
-
|
312
|
-
|
313
|
-
|
387
|
+
case
|
388
|
+
when COMMANDS.include?(normalized_command)
|
389
|
+
true
|
390
|
+
when !deprecations? && redis.respond_to?(command, include_all)
|
391
|
+
true
|
392
|
+
else
|
393
|
+
defined?(super) && super
|
314
394
|
end
|
315
|
-
|
316
|
-
defined?(super) && super
|
317
395
|
end
|
318
396
|
|
319
397
|
def call_with_namespace(command, *args, &block)
|
@@ -325,10 +403,14 @@ class Redis
|
|
325
403
|
|
326
404
|
(before, after) = handling
|
327
405
|
|
406
|
+
# Modify the local *args array in-place, no need to copy it.
|
407
|
+
args.map! {|arg| clone_args(arg)}
|
408
|
+
|
328
409
|
# Add the namespace to any parameters that are keys.
|
329
410
|
case before
|
330
411
|
when :first
|
331
412
|
args[0] = add_namespace(args[0]) if args[0]
|
413
|
+
args[-1] = ruby2_keywords_hash(args[-1]) if args[-1].is_a?(Hash)
|
332
414
|
when :all
|
333
415
|
args = add_namespace(args)
|
334
416
|
when :exclude_first
|
@@ -341,7 +423,7 @@ class Redis
|
|
341
423
|
args.push(last) if last
|
342
424
|
when :exclude_options
|
343
425
|
if args.last.is_a?(Hash)
|
344
|
-
last = args.pop
|
426
|
+
last = ruby2_keywords_hash(args.pop)
|
345
427
|
args = add_namespace(args)
|
346
428
|
args.push(last)
|
347
429
|
else
|
@@ -361,6 +443,7 @@ class Redis
|
|
361
443
|
args[1][:get].each_index do |i|
|
362
444
|
args[1][:get][i] = add_namespace(args[1][:get][i]) unless args[1][:get][i] == "#"
|
363
445
|
end
|
446
|
+
args[1] = ruby2_keywords_hash(args[1])
|
364
447
|
end
|
365
448
|
when :eval_style
|
366
449
|
# redis.eval() and evalsha() can either take the form:
|
@@ -381,7 +464,7 @@ class Redis
|
|
381
464
|
when :scan_style
|
382
465
|
options = (args.last.kind_of?(Hash) ? args.pop : {})
|
383
466
|
options[:match] = add_namespace(options.fetch(:match, '*'))
|
384
|
-
args << options
|
467
|
+
args << ruby2_keywords_hash(options)
|
385
468
|
|
386
469
|
if block
|
387
470
|
original_block = block
|
@@ -407,9 +490,35 @@ class Redis
|
|
407
490
|
|
408
491
|
result
|
409
492
|
end
|
493
|
+
ruby2_keywords(:call_with_namespace) if respond_to?(:ruby2_keywords, true)
|
410
494
|
|
411
495
|
private
|
412
496
|
|
497
|
+
if Hash.respond_to?(:ruby2_keywords_hash)
|
498
|
+
def ruby2_keywords_hash(kwargs)
|
499
|
+
Hash.ruby2_keywords_hash(kwargs)
|
500
|
+
end
|
501
|
+
else
|
502
|
+
def ruby2_keywords_hash(kwargs)
|
503
|
+
kwargs
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
# Avoid modifying the caller's (pass-by-reference) arguments.
|
508
|
+
def clone_args(arg)
|
509
|
+
if arg.is_a?(Array)
|
510
|
+
arg.map {|sub_arg| clone_args(sub_arg)}
|
511
|
+
elsif arg.is_a?(Hash)
|
512
|
+
Hash[arg.map {|k, v| [clone_args(k), clone_args(v)]}]
|
513
|
+
else
|
514
|
+
arg # Some objects (e.g. symbol) can't be dup'd.
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def call_site
|
519
|
+
caller.reject { |l| l.start_with?(__FILE__) }.first
|
520
|
+
end
|
521
|
+
|
413
522
|
def namespaced_block(command, &block)
|
414
523
|
redis.send(command) do |r|
|
415
524
|
begin
|
@@ -426,9 +535,10 @@ class Redis
|
|
426
535
|
|
427
536
|
case key
|
428
537
|
when Array
|
429
|
-
key.map {|k| add_namespace k}
|
538
|
+
key.map! {|k| add_namespace k}
|
430
539
|
when Hash
|
431
|
-
|
540
|
+
key.keys.each {|k| key[add_namespace(k)] = key.delete(k)}
|
541
|
+
key
|
432
542
|
else
|
433
543
|
"#{@namespace}:#{key}"
|
434
544
|
end
|