mock_redis 0.21.0 → 0.26.0
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 +4 -4
- data/.rubocop.yml +26 -5
- data/.rubocop_todo.yml +1 -1
- data/.travis.yml +3 -3
- data/CHANGELOG.md +33 -0
- data/Gemfile +2 -2
- data/LICENSE.md +21 -0
- data/README.md +37 -13
- data/lib/mock_redis.rb +0 -7
- data/lib/mock_redis/database.rb +42 -14
- data/lib/mock_redis/future.rb +1 -1
- data/lib/mock_redis/geospatial_methods.rb +4 -4
- data/lib/mock_redis/hash_methods.rb +18 -6
- data/lib/mock_redis/info_method.rb +2 -2
- data/lib/mock_redis/multi_db_wrapper.rb +2 -2
- data/lib/mock_redis/stream.rb +25 -2
- data/lib/mock_redis/stream/id.rb +1 -1
- data/lib/mock_redis/stream_methods.rb +16 -1
- data/lib/mock_redis/string_methods.rb +17 -9
- data/lib/mock_redis/transaction_wrapper.rb +2 -2
- data/lib/mock_redis/utility_methods.rb +6 -3
- data/lib/mock_redis/version.rb +1 -1
- data/lib/mock_redis/zset_methods.rb +52 -9
- data/mock_redis.gemspec +1 -2
- data/spec/commands/blpop_spec.rb +0 -6
- data/spec/commands/brpop_spec.rb +6 -5
- data/spec/commands/del_spec.rb +15 -0
- data/spec/commands/dump_spec.rb +19 -0
- data/spec/commands/exists_spec.rb +34 -5
- data/spec/commands/future_spec.rb +11 -1
- data/spec/commands/geoadd_spec.rb +1 -1
- data/spec/commands/hmset_spec.rb +26 -0
- data/spec/commands/hset_spec.rb +6 -6
- data/spec/commands/keys_spec.rb +17 -0
- data/spec/commands/mget_spec.rb +6 -0
- data/spec/commands/move_spec.rb +5 -5
- data/spec/commands/pipelined_spec.rb +20 -0
- data/spec/commands/restore_spec.rb +47 -0
- data/spec/commands/scan_spec.rb +9 -0
- data/spec/commands/set_spec.rb +8 -4
- data/spec/commands/setbit_spec.rb +1 -0
- data/spec/commands/setex_spec.rb +16 -0
- data/spec/commands/srandmember_spec.rb +1 -1
- data/spec/commands/xadd_spec.rb +20 -0
- data/spec/commands/xrange_spec.rb +13 -0
- data/spec/commands/xread_spec.rb +66 -0
- data/spec/commands/xtrim_spec.rb +6 -0
- data/spec/commands/zinterstore_spec.rb +34 -0
- data/spec/commands/zpopmax_spec.rb +60 -0
- data/spec/commands/zpopmin_spec.rb +60 -0
- data/spec/commands/zrange_spec.rb +1 -1
- data/spec/commands/zrangebyscore_spec.rb +1 -1
- data/spec/commands/zrevrange_spec.rb +1 -1
- data/spec/commands/zrevrangebyscore_spec.rb +1 -1
- data/spec/commands/zunionstore_spec.rb +33 -0
- data/spec/spec_helper.rb +4 -2
- data/spec/support/redis_multiplexer.rb +1 -0
- data/spec/transactions_spec.rb +16 -0
- metadata +16 -26
- data/LICENSE +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c087a47dd536c50c70b1238484a41a46669ca210b53063efd87fc863c83aaa67
|
4
|
+
data.tar.gz: 41927d6f1904768faaa5f9bbeff4fa803f7dc1045aa76da8f885594326eab326
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: efe4f6cb8a7c3326e8ad06c1753a651dc41323ca1fb4a7f23a1ac080feb09a4192f5d140ddeb437ce7268c0325e9e8bc4270f6d68facc88696d9586b9342d388
|
7
|
+
data.tar.gz: 7392d8b37355b3c22dd7c51745df2f67497dfb88f2534a5cf5df606e07b6fe47cc7969e4e005da85b4a4e382ef8b7801e220f948db71313330079781a973ff75
|
data/.rubocop.yml
CHANGED
@@ -3,10 +3,10 @@ inherit_from: .rubocop_todo.yml
|
|
3
3
|
AllCops:
|
4
4
|
TargetRubyVersion: 2.4
|
5
5
|
|
6
|
-
Layout/
|
6
|
+
Layout/ArgumentAlignment:
|
7
7
|
Enabled: false
|
8
8
|
|
9
|
-
Layout/
|
9
|
+
Layout/ParameterAlignment:
|
10
10
|
Enabled: false
|
11
11
|
|
12
12
|
Layout/DotPosition:
|
@@ -15,9 +15,21 @@ Layout/DotPosition:
|
|
15
15
|
Layout/EmptyLineAfterGuardClause:
|
16
16
|
Enabled: false
|
17
17
|
|
18
|
+
Layout/LineLength:
|
19
|
+
Max: 100
|
20
|
+
|
21
|
+
Layout/SpaceAroundMethodCallOperator:
|
22
|
+
Enabled: true
|
23
|
+
|
18
24
|
Lint/AssignmentInCondition:
|
19
25
|
Enabled: false
|
20
26
|
|
27
|
+
Lint/RaiseException:
|
28
|
+
Enabled: true
|
29
|
+
|
30
|
+
Lint/StructNewOverride:
|
31
|
+
Enabled: true
|
32
|
+
|
21
33
|
# We use this a lot in specs where it's perfectly valid
|
22
34
|
Lint/Void:
|
23
35
|
Exclude:
|
@@ -35,9 +47,6 @@ Metrics/CyclomaticComplexity:
|
|
35
47
|
Metrics/ClassLength:
|
36
48
|
Enabled: false
|
37
49
|
|
38
|
-
Metrics/LineLength:
|
39
|
-
Max: 100
|
40
|
-
|
41
50
|
Metrics/MethodLength:
|
42
51
|
Enabled: false
|
43
52
|
|
@@ -57,6 +66,18 @@ Style/Documentation:
|
|
57
66
|
Style/DoubleNegation:
|
58
67
|
Enabled: false
|
59
68
|
|
69
|
+
Style/ExponentialNotation:
|
70
|
+
Enabled: true
|
71
|
+
|
72
|
+
Style/HashEachMethods:
|
73
|
+
Enabled: true
|
74
|
+
|
75
|
+
Style/HashTransformKeys:
|
76
|
+
Enabled: true
|
77
|
+
|
78
|
+
Style/HashTransformValues:
|
79
|
+
Enabled: true
|
80
|
+
|
60
81
|
# We have too much code that relies on modifying strings
|
61
82
|
Style/FrozenStringLiteralComment:
|
62
83
|
Enabled: false
|
data/.rubocop_todo.yml
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
# Offense count: 17
|
10
10
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
11
11
|
# AllowedNames: io, id, to, by, on, in, at, ip
|
12
|
-
Naming/
|
12
|
+
Naming/MethodParameterName:
|
13
13
|
Exclude:
|
14
14
|
- 'lib/mock_redis/database.rb'
|
15
15
|
- 'lib/mock_redis/expire_wrapper.rb'
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,38 @@
|
|
1
1
|
# MockRedis Changelog
|
2
2
|
|
3
|
+
### 0.26.0
|
4
|
+
|
5
|
+
* Add block and count support to `xread` ([#194](https://github.com/sds/mock_redis/pull/194))
|
6
|
+
|
7
|
+
### 0.25.0
|
8
|
+
|
9
|
+
* Add support for `xread` command ([#190](https://github.com/sds/mock_redis/pull/190))
|
10
|
+
* Fix `mget` to raise error when passing empty array ([#191](https://github.com/sds/mock_redis/pull/191))
|
11
|
+
* Fix `xadd` when `maxlen` is zero ([#192](https://github.com/sds/mock_redis/pull/192))
|
12
|
+
|
13
|
+
### 0.24.0
|
14
|
+
|
15
|
+
* Fix handling of blocks within `multi` blocks ([#185](https://github.com/sds/mock_redis/pull/185))
|
16
|
+
* Fix handling of multiple consecutive `?` characters in key pattern matching ([#186](https://github.com/sds/mock_redis/pull/186))
|
17
|
+
* Change `exists` to return an integer and add `exists?` ([#188](https://github.com/sds/mock_redis/pull/188))
|
18
|
+
|
19
|
+
### 0.23.0
|
20
|
+
|
21
|
+
* Raise error when `setex` called with negative timeout ([#174](https://github.com/sds/mock_redis/pull/174))
|
22
|
+
* Add support for `dump`/`restore` between MockRedis instances ([#176](https://github.com/sds/mock_redis/pull/176))
|
23
|
+
* Fix warnings for ZSET methods on Ruby 2.7 ([#177](https://github.com/sds/mock_redis/pull/177))
|
24
|
+
* Add support for returning time in pipelines ([#179](https://github.com/sds/mock_redis/pull/179))
|
25
|
+
* Fix SET methods to correct set milliseconds with `px` ([#180](https://github.com/sds/mock_redis/pull/180))
|
26
|
+
* Add support for unsorted sets within `zinterstore`/`zunionstore`([#182](https://github.com/sds/mock_redis/pull/182))
|
27
|
+
|
28
|
+
### 0.22.0
|
29
|
+
|
30
|
+
* Gracefully handle cursors larger than the collection size in scan commands ([#171](https://github.com/sds/mock_redis/pull/171))
|
31
|
+
* Add `zpopmin` and `zpopmax` commands ([#172](https://github.com/sds/mock_redis/pull/172))
|
32
|
+
* Fix `hmset` to support array arguments ([#173](https://github.com/sds/mock_redis/pull/173))
|
33
|
+
* Fix `hmset` to always treat keys as strings ([#173](https://github.com/sds/mock_redis/pull/173))
|
34
|
+
* Remove unnecessary dependency on `rake` gem
|
35
|
+
|
3
36
|
### 0.21.0
|
4
37
|
|
5
38
|
* Fix behavior of `time` to return array of two integers ([#161](https://github.com/sds/mock_redis/pull/161))
|
data/Gemfile
CHANGED
@@ -4,9 +4,9 @@ source 'http://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
# Run all pre-commit hooks via Overcommit during CI runs
|
7
|
-
gem 'overcommit', '0.
|
7
|
+
gem 'overcommit', '0.53.0'
|
8
8
|
|
9
9
|
# Pin tool versions (which are executed by Overcommit) for Travis builds
|
10
|
-
gem 'rubocop', '0.
|
10
|
+
gem 'rubocop', '0.82.0'
|
11
11
|
|
12
12
|
gem 'coveralls', require: false
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MockRedis released under the MIT license.
|
2
|
+
|
3
|
+
> Copyright (c) Shane da Silva. http://shane.io
|
4
|
+
>
|
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:
|
11
|
+
>
|
12
|
+
> The above copyright notice and this permission notice shall be included in
|
13
|
+
> all copies or substantial portions of the Software.
|
14
|
+
>
|
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
@@ -8,11 +8,20 @@ MockRedis provides the same interface as `redis-rb`, but it stores its
|
|
8
8
|
data in memory instead of talking to a Redis server. It is intended
|
9
9
|
for use in tests.
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
## Requirements
|
12
|
+
|
13
|
+
* Ruby 2.4+
|
14
|
+
|
15
|
+
The current implementation is tested against **Redis 5**. Older versions may work, but can also return different results or not support some commands.
|
13
16
|
|
14
17
|
## Getting Started
|
15
18
|
|
19
|
+
Install the gem:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
gem install mock_redis
|
23
|
+
```
|
24
|
+
|
16
25
|
It's as easy as `require 'mock_redis'; mr = MockRedis.new`. Then you can
|
17
26
|
call the same methods on it as you can call on a real `Redis` object.
|
18
27
|
|
@@ -90,17 +99,32 @@ please submit a pull request with your (tested!) implementation.
|
|
90
99
|
* `#config(:get|:set|:resetstat)` isn't done. They can just return
|
91
100
|
canned values.
|
92
101
|
|
93
|
-
##
|
102
|
+
## Running tests
|
103
|
+
|
104
|
+
We recommend running Redis within a Docker container to make development as simple as possible, but as long as you have a Redis instance listening on `localhost:6379` you should be good to go.
|
105
|
+
|
106
|
+
1. Start Redis.
|
107
|
+
```bash
|
108
|
+
docker run --rm -p 6379:6379 redis
|
109
|
+
```
|
110
|
+
2. Install dependencies.
|
111
|
+
```bash
|
112
|
+
bundle install
|
113
|
+
```
|
114
|
+
3. Run tests.
|
115
|
+
```bash
|
116
|
+
bundle exec rspec
|
117
|
+
```
|
118
|
+
|
119
|
+
These tests were written with Redis running on `localhost` without any
|
120
|
+
passwords required. If you're using a different version of Redis, you
|
121
|
+
may see failures due to error message text being different and other
|
122
|
+
breaking changes over time.
|
123
|
+
|
124
|
+
## Changelog
|
94
125
|
|
95
|
-
|
96
|
-
older versions of Ruby, use `0.18.0` or older.
|
126
|
+
If you're interested in seeing the changes and bug fixes between each version of `mock_redis`, read the [MockRedis Changelog](CHANGELOG.md).
|
97
127
|
|
98
|
-
##
|
128
|
+
## License
|
99
129
|
|
100
|
-
|
101
|
-
tests. (Just kidding! There's no probably about it.) These tests were
|
102
|
-
written with Redis running on `localhost` without any passwords
|
103
|
-
required. If you're using a different version of Redis, you may see
|
104
|
-
failures due to error message text being different. If you're running
|
105
|
-
a really old version of Redis, you'll definitely see failures due to
|
106
|
-
stuff that doesn't work!
|
130
|
+
This project is released under the [MIT license](LICENSE.md).
|
data/lib/mock_redis.rb
CHANGED
@@ -64,13 +64,6 @@ class MockRedis
|
|
64
64
|
options[:db]
|
65
65
|
end
|
66
66
|
|
67
|
-
def now
|
68
|
-
current_time = options[:time_class].now
|
69
|
-
miliseconds = (current_time.to_r - current_time.to_i) * 1_000
|
70
|
-
[current_time.to_i, miliseconds.to_i]
|
71
|
-
end
|
72
|
-
alias time now
|
73
|
-
|
74
67
|
def time_at(timestamp)
|
75
68
|
options[:time_class].at(timestamp)
|
76
69
|
end
|
data/lib/mock_redis/database.rb
CHANGED
@@ -35,7 +35,7 @@ class MockRedis
|
|
35
35
|
|
36
36
|
def initialize_copy(_source)
|
37
37
|
@data = @data.clone
|
38
|
-
@data.
|
38
|
+
@data.each_key { |k| @data[k] = @data[k].clone }
|
39
39
|
@expire_times = @expire_times.map(&:clone)
|
40
40
|
end
|
41
41
|
|
@@ -106,7 +106,7 @@ class MockRedis
|
|
106
106
|
raise Redis::CommandError, 'ERR value is not an integer or out of range'
|
107
107
|
end
|
108
108
|
|
109
|
-
if exists(key)
|
109
|
+
if exists?(key)
|
110
110
|
timestamp = Rational(timestamp_ms.to_i, 1000)
|
111
111
|
set_expiration(key, @base.time_at(timestamp))
|
112
112
|
true
|
@@ -115,12 +115,33 @@ class MockRedis
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
-
def exists(
|
119
|
-
data.key?(key)
|
118
|
+
def exists(*keys)
|
119
|
+
keys.count { |key| data.key?(key) }
|
120
|
+
end
|
121
|
+
|
122
|
+
def exists?(*keys)
|
123
|
+
keys.each { |key| return true if data.key?(key) }
|
124
|
+
false
|
120
125
|
end
|
121
126
|
|
122
127
|
def flushdb
|
123
|
-
data.
|
128
|
+
data.each_key { |k| del(k) }
|
129
|
+
'OK'
|
130
|
+
end
|
131
|
+
|
132
|
+
def dump(key)
|
133
|
+
value = data[key]
|
134
|
+
value ? Marshal.dump(value) : nil
|
135
|
+
end
|
136
|
+
|
137
|
+
def restore(key, ttl, value, replace: false)
|
138
|
+
if !replace && exists?(key)
|
139
|
+
raise Redis::CommandError, 'BUSYKEY Target key name already exists.'
|
140
|
+
end
|
141
|
+
data[key] = Marshal.load(value) # rubocop:disable Security/MarshalLoad
|
142
|
+
if ttl > 0
|
143
|
+
pexpire(key, ttl)
|
144
|
+
end
|
124
145
|
'OK'
|
125
146
|
end
|
126
147
|
|
@@ -143,11 +164,11 @@ class MockRedis
|
|
143
164
|
end
|
144
165
|
|
145
166
|
def lastsave
|
146
|
-
|
167
|
+
now.first
|
147
168
|
end
|
148
169
|
|
149
170
|
def persist(key)
|
150
|
-
if exists(key) && has_expiration?(key)
|
171
|
+
if exists?(key) && has_expiration?(key)
|
151
172
|
remove_expiration(key)
|
152
173
|
true
|
153
174
|
else
|
@@ -188,7 +209,7 @@ class MockRedis
|
|
188
209
|
raise Redis::CommandError, 'ERR no such key'
|
189
210
|
end
|
190
211
|
|
191
|
-
if exists(newkey)
|
212
|
+
if exists?(newkey)
|
192
213
|
false
|
193
214
|
else
|
194
215
|
rename(key, newkey)
|
@@ -201,7 +222,7 @@ class MockRedis
|
|
201
222
|
end
|
202
223
|
|
203
224
|
def ttl(key)
|
204
|
-
if !exists(key)
|
225
|
+
if !exists?(key)
|
205
226
|
-2
|
206
227
|
elsif has_expiration?(key)
|
207
228
|
now, = @base.now
|
@@ -215,7 +236,7 @@ class MockRedis
|
|
215
236
|
now, miliseconds = @base.now
|
216
237
|
now_ms = now * 1000 + miliseconds
|
217
238
|
|
218
|
-
if !exists(key)
|
239
|
+
if !exists?(key)
|
219
240
|
-2
|
220
241
|
elsif has_expiration?(key)
|
221
242
|
(expiration(key).to_r * 1000).to_i - now_ms
|
@@ -224,8 +245,15 @@ class MockRedis
|
|
224
245
|
end
|
225
246
|
end
|
226
247
|
|
248
|
+
def now
|
249
|
+
current_time = @base.options[:time_class].now
|
250
|
+
miliseconds = (current_time.to_r - current_time.to_i) * 1_000
|
251
|
+
[current_time.to_i, miliseconds.to_i]
|
252
|
+
end
|
253
|
+
alias time now
|
254
|
+
|
227
255
|
def type(key)
|
228
|
-
if !exists(key)
|
256
|
+
if !exists?(key)
|
229
257
|
'none'
|
230
258
|
elsif hashy?(key)
|
231
259
|
'hash'
|
@@ -300,7 +328,7 @@ class MockRedis
|
|
300
328
|
Regexp.new(
|
301
329
|
"^#{pattern}$".
|
302
330
|
gsub(/([+|()])/, '\\\\\1').
|
303
|
-
gsub(/(
|
331
|
+
gsub(/(?<!\\)\?/, '\\1.').
|
304
332
|
gsub(/([^\\])\*/, '\\1.*')
|
305
333
|
)
|
306
334
|
end
|
@@ -328,8 +356,8 @@ class MockRedis
|
|
328
356
|
# This method isn't private, but it also isn't a Redis command, so
|
329
357
|
# it doesn't belong up above with all the Redis commands.
|
330
358
|
def expire_keys
|
331
|
-
|
332
|
-
now_ms =
|
359
|
+
now_sec, miliseconds = now
|
360
|
+
now_ms = now_sec * 1_000 + miliseconds
|
333
361
|
|
334
362
|
to_delete = expire_times.take_while do |(time, _key)|
|
335
363
|
(time.to_r * 1_000).to_i <= now_ms
|
data/lib/mock_redis/future.rb
CHANGED
@@ -38,7 +38,7 @@ class MockRedis
|
|
38
38
|
lng2, lat2 = geohash_decode(hash2)
|
39
39
|
|
40
40
|
distance = geohash_distance(lng1, lat1, lng2, lat2) / to_meter
|
41
|
-
format('
|
41
|
+
format('%<distance>.4f', distance: distance)
|
42
42
|
end
|
43
43
|
|
44
44
|
def geohash(key, members)
|
@@ -95,8 +95,8 @@ class MockRedis
|
|
95
95
|
lat = Float(point[1])
|
96
96
|
|
97
97
|
unless LNG_RANGE.include?(lng) && LAT_RANGE.include?(lat)
|
98
|
-
lng = format('
|
99
|
-
lat = format('
|
98
|
+
lng = format('%<long>.6f', long: lng)
|
99
|
+
lat = format('%<lat>.6f', lat: lat)
|
100
100
|
raise Redis::CommandError,
|
101
101
|
"ERR invalid longitude,latitude pair #{lng},#{lat}"
|
102
102
|
end
|
@@ -201,7 +201,7 @@ class MockRedis
|
|
201
201
|
end
|
202
202
|
|
203
203
|
def format_decoded_coord(coord)
|
204
|
-
coord = format('
|
204
|
+
coord = format('%<coord>.17f', coord: coord)
|
205
205
|
l = 1
|
206
206
|
l += 1 while coord[-l] == '0'
|
207
207
|
coord = coord[0..-l]
|
@@ -84,10 +84,17 @@ class MockRedis
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def hmset(key, *kvpairs)
|
87
|
+
if key.is_a? Array
|
88
|
+
err_msg = 'ERR wrong number of arguments for \'hmset\' command'
|
89
|
+
kvpairs = key[1..-1]
|
90
|
+
key = key[0]
|
91
|
+
end
|
92
|
+
|
87
93
|
kvpairs.flatten!
|
88
94
|
assert_has_args(kvpairs, 'hmset')
|
95
|
+
|
89
96
|
if kvpairs.length.odd?
|
90
|
-
raise Redis::CommandError, 'ERR wrong number of arguments for HMSET'
|
97
|
+
raise Redis::CommandError, err_msg || 'ERR wrong number of arguments for HMSET'
|
91
98
|
end
|
92
99
|
|
93
100
|
kvpairs.each_slice(2) do |(k, v)|
|
@@ -121,10 +128,15 @@ class MockRedis
|
|
121
128
|
end
|
122
129
|
end
|
123
130
|
|
124
|
-
def hset(key,
|
125
|
-
|
126
|
-
with_hash_at(key)
|
127
|
-
|
131
|
+
def hset(key, *args)
|
132
|
+
added = 0
|
133
|
+
with_hash_at(key) do |hash|
|
134
|
+
args.each_slice(2) do |field, value|
|
135
|
+
added += 1 unless hash.key?(field.to_s)
|
136
|
+
hash[field.to_s] = value.to_s
|
137
|
+
end
|
138
|
+
end
|
139
|
+
added
|
128
140
|
end
|
129
141
|
|
130
142
|
def hsetnx(key, field, value)
|
@@ -143,7 +155,7 @@ class MockRedis
|
|
143
155
|
private
|
144
156
|
|
145
157
|
def with_hash_at(key, &blk)
|
146
|
-
with_thing_at(key, :assert_hashy, proc { {} }, &blk)
|
158
|
+
with_thing_at(key.to_s, :assert_hashy, proc { {} }, &blk)
|
147
159
|
end
|
148
160
|
|
149
161
|
def hashy?(key)
|