redis-namespace 1.5.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|