redis-objects 1.7.0 → 2.0.0.beta
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/CHANGELOG.rdoc +8 -0
- data/README.md +54 -4
- data/lib/redis/list.rb +2 -10
- data/lib/redis/objects/locks.rb +1 -1
- data/lib/redis/objects/version.rb +1 -1
- data/lib/redis/objects.rb +84 -7
- data/lib/redis/set.rb +2 -1
- data/lib/redis/sorted_set.rb +2 -2
- data/redis-objects.gemspec +1 -1
- data/spec/redis_legacy_key_naming_spec.rb +419 -0
- data/spec/redis_objects_conn_spec.rb +4 -14
- data/spec/redis_objects_instance_spec.rb +41 -28
- data/spec/redis_objects_model_spec.rb +8 -4
- data/spec/spec_helper.rb +2 -2
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3962b1b4d04b8b94a6d130f2323fe1f93a74cce5546285b011ccbb85293afa5d
|
4
|
+
data.tar.gz: cfba25072de6ac2801100f2a11aa0588dc872e0826d88c070327c3be688a9260
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64a0743cbe2f89145510e00877f2954f6734bdd472c0b272ac165912dffb4ef9d03b395ee7c63bf6a5c06504f6340cf761e69cca0f9fdf5285895b3a544e38b3
|
7
|
+
data.tar.gz: eb7cc427ed879586363b84ed1b509052a23e5bf56d7ef8621d5b9fc6d8c4fea3ec20672a1569d018f45530ac131f9e68772213192c6c42baf50beaa7cec977a5
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
= Changelog for Redis::Objects
|
2
2
|
|
3
|
+
== 2.0.0.beta (30 Mar 2023)
|
4
|
+
|
5
|
+
* Updated internal calls to match `redis-rb`
|
6
|
+
|
7
|
+
* INCOMPAT: `Redis.current` is no longer allowed due to changes in `redis-rb`
|
8
|
+
|
9
|
+
* INCOMPAT: The order of items popped off a list by the rarely-used command `list.pop(n)` to specify multiple elements is now reversed to match redis.
|
10
|
+
|
3
11
|
== 1.7.0 (29 Apr 2022)
|
4
12
|
|
5
13
|
* Bumped version to 1.7.0 to revert redis-rb version lock [Nate Wiger]
|
data/README.md
CHANGED
@@ -5,6 +5,56 @@ Redis::Objects - Map Redis types directly to Ruby objects
|
|
5
5
|
[](https://codecov.io/gh/nateware/redis-objects)
|
6
6
|
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MJF7JU5M7F8VL)
|
7
7
|
|
8
|
+
Important 2.0 changes
|
9
|
+
=====================
|
10
|
+
Redis::Objects 2.0 introduces several important backwards incompatible changes.
|
11
|
+
Currently 2.0 can be installed with `gem install redis-objects --pre` or by listing it
|
12
|
+
explicitly in your Gemfile:
|
13
|
+
~~~ruby
|
14
|
+
# Gemfile
|
15
|
+
gem 'redis-objects', '>= 2.0.0.beta'
|
16
|
+
~~~
|
17
|
+
You're encouraged to try it out in test code (not production) to ensure it works for you.
|
18
|
+
Official release is expected later in 2023.
|
19
|
+
|
20
|
+
Key Naming Changes
|
21
|
+
------------------
|
22
|
+
The internal key naming scheme has changed for `Nested::Class::Namespaces` to fix a longstanding bug.
|
23
|
+
**This means your existing data in Redis will not be accessible until you call `migrate_redis_legacy_keys`.**
|
24
|
+
|
25
|
+
To fix this (only needed once), create a script like this:
|
26
|
+
|
27
|
+
~~~ruby
|
28
|
+
class YouClassNameHere < ActiveRecord::Base
|
29
|
+
include Redis::Objects
|
30
|
+
# ... your relevant definitions here ...
|
31
|
+
end
|
32
|
+
|
33
|
+
YourClassName.migrate_redis_legacy_keys
|
34
|
+
~~~
|
35
|
+
|
36
|
+
Then, you need to find a time when you can temporarily pause writes to your redis server
|
37
|
+
so that you can run that script. It uses `redis.scan` internally so it should be able to
|
38
|
+
handle a high number of keys. For large data sets, it could take a while.
|
39
|
+
|
40
|
+
For more details on the issue and fix refer to [#213](https://github.com/nateware/redis-objects/issues/231).
|
41
|
+
|
42
|
+
Renaming of `lock` Method
|
43
|
+
-------------------------
|
44
|
+
The `lock` method that collided with `ActiveRecord::Base` has been renamed `redis_lock`.
|
45
|
+
This means your classes need to be updated to call `redis_lock` instead:
|
46
|
+
|
47
|
+
~~~ruby
|
48
|
+
class YouClassNameHere < ActiveRecord::Base
|
49
|
+
include Redis::Objects
|
50
|
+
redis_lock :mylock # formerly just "lock"
|
51
|
+
end
|
52
|
+
~~~
|
53
|
+
|
54
|
+
For more details on the issue and fix refer to [#196](https://github.com/nateware/redis-objects/issues/196).
|
55
|
+
|
56
|
+
Overview
|
57
|
+
--------
|
8
58
|
This is **not** an ORM. People that are wrapping ORM’s around Redis are missing the point.
|
9
59
|
|
10
60
|
The killer feature of Redis is that it allows you to perform _atomic_ operations
|
@@ -119,7 +169,7 @@ Here's an example that integrates several data types with an ActiveRecord model:
|
|
119
169
|
class Team < ActiveRecord::Base
|
120
170
|
include Redis::Objects
|
121
171
|
|
122
|
-
|
172
|
+
redis_lock :trade_players, :expiration => 15 # sec
|
123
173
|
value :at_bat
|
124
174
|
counter :hits
|
125
175
|
counter :runs
|
@@ -524,7 +574,7 @@ Locks work similarly. On completion or exception the lock is released:
|
|
524
574
|
|
525
575
|
~~~ruby
|
526
576
|
class Team < ActiveRecord::Base
|
527
|
-
|
577
|
+
redis_lock :reorder # declare a lock
|
528
578
|
end
|
529
579
|
|
530
580
|
@team.reorder_lock.lock do
|
@@ -548,7 +598,7 @@ lock time.
|
|
548
598
|
|
549
599
|
~~~ruby
|
550
600
|
class Team < ActiveRecord::Base
|
551
|
-
|
601
|
+
redis_lock :reorder, :expiration => 15.minutes
|
552
602
|
end
|
553
603
|
~~~
|
554
604
|
|
@@ -596,5 +646,5 @@ end
|
|
596
646
|
|
597
647
|
Author
|
598
648
|
=======
|
599
|
-
Copyright (c) 2009-
|
649
|
+
Copyright (c) 2009-2022 [Nate Wiger](http://nateware.com). All Rights Reserved.
|
600
650
|
Released under the [Artistic License](http://www.opensource.org/licenses/artistic-license-2.0.php).
|
data/lib/redis/list.rb
CHANGED
@@ -31,11 +31,7 @@ class Redis
|
|
31
31
|
# Remove a member from the end of the list. Redis: RPOP
|
32
32
|
def pop(n=nil)
|
33
33
|
if n
|
34
|
-
|
35
|
-
redis.lrange(key, -n, -1)
|
36
|
-
redis.ltrim(key, 0, -n - 1)
|
37
|
-
end
|
38
|
-
unmarshal result
|
34
|
+
unmarshal redis.rpop(key, n)
|
39
35
|
else
|
40
36
|
unmarshal redis.rpop(key)
|
41
37
|
end
|
@@ -65,11 +61,7 @@ class Redis
|
|
65
61
|
# Remove a member from the start of the list. Redis: LPOP
|
66
62
|
def shift(n=nil)
|
67
63
|
if n
|
68
|
-
|
69
|
-
redis.lrange(key, 0, n - 1)
|
70
|
-
redis.ltrim(key, n, -1)
|
71
|
-
end
|
72
|
-
unmarshal result
|
64
|
+
unmarshal redis.lpop(key, n)
|
73
65
|
else
|
74
66
|
unmarshal redis.lpop(key)
|
75
67
|
end
|
data/lib/redis/objects/locks.rb
CHANGED
@@ -14,7 +14,7 @@ class Redis
|
|
14
14
|
module ClassMethods
|
15
15
|
# Define a new lock. It will function like a model attribute,
|
16
16
|
# so it can be used alongside ActiveRecord/DataMapper, etc.
|
17
|
-
def
|
17
|
+
def redis_lock(name, options={})
|
18
18
|
options[:timeout] ||= 5 # seconds
|
19
19
|
lock_name = "#{name}_lock"
|
20
20
|
redis_objects[lock_name.to_sym] = options.merge(:type => :lock)
|
data/lib/redis/objects.rb
CHANGED
@@ -62,7 +62,7 @@ class Redis
|
|
62
62
|
@redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
|
63
63
|
end
|
64
64
|
def redis
|
65
|
-
@redis || $redis ||
|
65
|
+
@redis || $redis ||
|
66
66
|
raise(NotConnected, "Redis::Objects.redis not set to a Redis.new connection")
|
67
67
|
end
|
68
68
|
|
@@ -101,16 +101,93 @@ class Redis
|
|
101
101
|
@redis_objects ||= {}
|
102
102
|
end
|
103
103
|
|
104
|
-
#
|
105
|
-
|
104
|
+
# Toggles whether to use the legacy redis key naming scheme, which causes
|
105
|
+
# naming conflicts in certain cases.
|
106
|
+
attr_accessor :redis_legacy_naming
|
107
|
+
attr_accessor :redis_silence_warnings
|
108
|
+
|
109
|
+
# Set the Redis redis_prefix to use. Defaults to class_name.
|
110
|
+
def redis_prefix=(redis_prefix)
|
111
|
+
@silence_warnings_as_redis_prefix_was_set_manually = true
|
112
|
+
@redis_prefix = redis_prefix
|
113
|
+
end
|
114
|
+
|
106
115
|
def redis_prefix(klass = self) #:nodoc:
|
107
|
-
@redis_prefix ||=
|
108
|
-
|
109
|
-
|
110
|
-
|
116
|
+
@redis_prefix ||=
|
117
|
+
if redis_legacy_naming
|
118
|
+
redis_legacy_prefix(klass)
|
119
|
+
else
|
120
|
+
redis_legacy_naming_warning_message(klass)
|
121
|
+
redis_modern_prefix(klass)
|
122
|
+
end
|
123
|
+
|
124
|
+
@redis_prefix
|
125
|
+
end
|
126
|
+
|
127
|
+
def redis_modern_prefix(klass = self) #:nodoc:
|
128
|
+
klass.name.to_s.
|
129
|
+
gsub(/::/, '__'). # Nested::Class => Nested__Class
|
130
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). # ClassName => Class_Name
|
131
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2'). # className => class_Name
|
132
|
+
downcase
|
133
|
+
end
|
134
|
+
|
135
|
+
def redis_legacy_prefix(klass = self) #:nodoc:
|
136
|
+
klass.name.to_s.
|
137
|
+
sub(%r{(.*::)}, ''). # Nested::Class => Class (problematic)
|
138
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). # ClassName => Class_Name
|
139
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2'). # className => class_Name
|
111
140
|
downcase
|
112
141
|
end
|
113
142
|
|
143
|
+
# Temporary warning to help with migrating key names
|
144
|
+
def redis_legacy_naming_warning_message(klass)
|
145
|
+
# warn @silence_warnings_as_redis_prefix_was_set_manually.inspect
|
146
|
+
unless redis_legacy_naming || redis_silence_warnings || @silence_warnings_as_redis_prefix_was_set_manually
|
147
|
+
modern = redis_modern_prefix(klass)
|
148
|
+
legacy = redis_legacy_prefix(klass)
|
149
|
+
if modern != legacy
|
150
|
+
warn <<EOW
|
151
|
+
[redis-objects] WARNING: In redis-objects 2.0.0, key naming will change to fix longstanding bugs.
|
152
|
+
[redis-objects] Your class #{klass.name.to_s} will be affected by this change!
|
153
|
+
[redis-objects] Current key prefix: #{legacy.inspect}
|
154
|
+
[redis-objects] Future key prefix: #{modern.inspect}
|
155
|
+
[redis-objects] Read more at https://github.com/nateware/redis-objects/issues/231
|
156
|
+
EOW
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def migrate_redis_legacy_keys
|
162
|
+
cursor = 0
|
163
|
+
legacy = redis_legacy_prefix
|
164
|
+
total_keys = 0
|
165
|
+
if legacy == redis_prefix
|
166
|
+
raise "Failed to migrate keys for #{self.name.to_s} as legacy and new redis_prefix are the same (#{redis_prefix})"
|
167
|
+
end
|
168
|
+
warn "[redis-objects] Migrating keys from #{legacy} prefix to #{redis_prefix}"
|
169
|
+
|
170
|
+
loop do
|
171
|
+
cursor, keys = redis.scan(cursor, :match => "#{legacy}:*")
|
172
|
+
total_keys += keys.length
|
173
|
+
keys.each do |key|
|
174
|
+
# Split key name apart on ':'
|
175
|
+
base_class, id, name = key.split(':')
|
176
|
+
|
177
|
+
# Figure out the new name
|
178
|
+
new_key = redis_field_key(name, id=id, context=self)
|
179
|
+
|
180
|
+
# Rename the key
|
181
|
+
warn "[redis-objects] Rename '#{key}', '#{new_key}'"
|
182
|
+
ok = redis.rename(key, new_key)
|
183
|
+
warn "[redis-objects] Warning: Rename '#{key}', '#{new_key}' failed: #{ok}" if ok != 'OK'
|
184
|
+
end
|
185
|
+
break if cursor == "0"
|
186
|
+
end
|
187
|
+
|
188
|
+
warn "[redis-objects] Migrated #{total_keys} total number of redis keys"
|
189
|
+
end
|
190
|
+
|
114
191
|
def redis_options(name)
|
115
192
|
klass = first_ancestor_with(name)
|
116
193
|
return klass.redis_objects[name.to_sym] || {}
|
data/lib/redis/set.rb
CHANGED
@@ -15,7 +15,8 @@ class Redis
|
|
15
15
|
# Redis: SADD
|
16
16
|
def add(value)
|
17
17
|
allow_expiration do
|
18
|
-
|
18
|
+
value = '' if value.nil?
|
19
|
+
redis.sadd(key, marshal(value)) if !Array(value).empty? # allow empty adds
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
data/lib/redis/sorted_set.rb
CHANGED
@@ -211,7 +211,7 @@ class Redis
|
|
211
211
|
result = redis.zrange(temp_key, 0, -1)
|
212
212
|
end
|
213
213
|
|
214
|
-
result
|
214
|
+
result
|
215
215
|
end
|
216
216
|
alias_method :intersect, :intersection
|
217
217
|
alias_method :inter, :intersection
|
@@ -248,7 +248,7 @@ class Redis
|
|
248
248
|
result = redis.zrange(temp_key, 0, -1)
|
249
249
|
end
|
250
250
|
|
251
|
-
result
|
251
|
+
result
|
252
252
|
end
|
253
253
|
alias_method :|, :union
|
254
254
|
alias_method :+, :union
|
data/redis-objects.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
# Only fix this one version or else tests break
|
22
|
-
spec.add_dependency "redis"
|
22
|
+
spec.add_dependency "redis", '~> 5.0'
|
23
23
|
|
24
24
|
# Ignore gemspec warnings on these. Trying to fix them to versions breaks TravisCI
|
25
25
|
spec.add_development_dependency "bundler"
|
@@ -0,0 +1,419 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'redis/objects'
|
4
|
+
Redis::Objects.redis = REDIS_HANDLE
|
5
|
+
|
6
|
+
require 'securerandom'
|
7
|
+
|
8
|
+
require "stringio"
|
9
|
+
|
10
|
+
def capture_stderr
|
11
|
+
# The output stream must be an IO-like object. In this case we capture it in
|
12
|
+
# an in-memory IO object so we can return the string value. You can assign any
|
13
|
+
# IO object here.
|
14
|
+
previous_stderr, $stderr = $stderr, StringIO.new
|
15
|
+
yield
|
16
|
+
$stderr.string
|
17
|
+
ensure
|
18
|
+
# Restore the previous value of stderr (typically equal to STDERR).
|
19
|
+
$stderr = previous_stderr
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'Legacy redis key prefix naming compatibility' do
|
23
|
+
it 'verifies single level classes work the same' do
|
24
|
+
class SingleLevelOne
|
25
|
+
include Redis::Objects
|
26
|
+
|
27
|
+
def id
|
28
|
+
1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
obj = SingleLevelOne.new
|
33
|
+
obj.class.redis_prefix.should == 'single_level_one'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'verifies single level classes obey the legacy naming flag' do
|
37
|
+
class SingleLevelTwo
|
38
|
+
include Redis::Objects
|
39
|
+
self.redis_legacy_naming = true
|
40
|
+
|
41
|
+
def id
|
42
|
+
1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
obj = SingleLevelTwo.new
|
47
|
+
obj.class.redis_prefix.should == 'single_level_two'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'verifies nested classes do NOT work the same' do
|
51
|
+
module Nested
|
52
|
+
class NamingOne
|
53
|
+
include Redis::Objects
|
54
|
+
self.redis_silence_warnings = true
|
55
|
+
|
56
|
+
def id
|
57
|
+
1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
obj = Nested::NamingOne.new
|
63
|
+
obj.class.redis_prefix.should == 'nested__naming_one'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'verifies the legacy naming flag is respected' do
|
67
|
+
module Nested
|
68
|
+
class NamingTwo
|
69
|
+
include Redis::Objects
|
70
|
+
self.redis_legacy_naming = true
|
71
|
+
self.redis_silence_warnings = true
|
72
|
+
|
73
|
+
def id
|
74
|
+
1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Nested::NamingTwo.redis_legacy_naming.should == true
|
80
|
+
obj = Nested::NamingTwo.new
|
81
|
+
obj.class.redis_prefix.should == 'naming_two'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'verifies that multiple levels respect __ vs _' do
|
85
|
+
module NestedLevel
|
86
|
+
module Further
|
87
|
+
class NamingThree
|
88
|
+
include Redis::Objects
|
89
|
+
self.redis_silence_warnings = true
|
90
|
+
|
91
|
+
def id
|
92
|
+
1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
obj = NestedLevel::Further::NamingThree.new
|
99
|
+
obj.class.redis_prefix.should == 'nested_level__further__naming_three'
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'verifies that multiple levels respect the legacy naming' do
|
103
|
+
module NestedLevel
|
104
|
+
module Further
|
105
|
+
class NamingFour
|
106
|
+
include Redis::Objects
|
107
|
+
self.redis_legacy_naming = true
|
108
|
+
|
109
|
+
def id
|
110
|
+
1
|
111
|
+
end
|
112
|
+
|
113
|
+
redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 31)
|
114
|
+
value :redis_value, :redis => redis_handle
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
NestedLevel::Further::NamingFour.redis_legacy_naming.should == true
|
120
|
+
obj = NestedLevel::Further::NamingFour.new
|
121
|
+
obj.class.redis_prefix.should == 'naming_four'
|
122
|
+
val = SecureRandom.hex(10)
|
123
|
+
obj.redis_value = val
|
124
|
+
obj.redis_value.should == val
|
125
|
+
obj.redis_value.key.should == 'naming_four:1:redis_value'
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'verifies that multiple levels do not conflict 1' do
|
129
|
+
module NestedLevel
|
130
|
+
module Further
|
131
|
+
class NamingFive
|
132
|
+
include Redis::Objects
|
133
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
134
|
+
self.redis_silence_warnings = true
|
135
|
+
|
136
|
+
def id
|
137
|
+
1
|
138
|
+
end
|
139
|
+
|
140
|
+
value :redis_value
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
obj = NestedLevel::Further::NamingFive.new
|
146
|
+
obj.class.redis_prefix.should == 'nested_level__further__naming_five'
|
147
|
+
val = SecureRandom.hex(10)
|
148
|
+
obj.redis_value = val
|
149
|
+
obj.redis_value.should == val
|
150
|
+
obj.redis_value.key.should == 'nested_level__further__naming_five:1:redis_value'
|
151
|
+
obj.redis_value.redis.should == obj.redis
|
152
|
+
obj.redis.get('nested_level__further__naming_five:1:redis_value').should == val
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'verifies that multiple levels do not conflict 2' do
|
156
|
+
module Nested
|
157
|
+
module LevelFurtherNaming
|
158
|
+
class Five
|
159
|
+
include Redis::Objects
|
160
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
161
|
+
self.redis_silence_warnings = true
|
162
|
+
|
163
|
+
def id
|
164
|
+
1
|
165
|
+
end
|
166
|
+
|
167
|
+
value :redis_value
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
obj = Nested::LevelFurtherNaming::Five.new
|
173
|
+
obj.class.redis_prefix.should == 'nested__level_further_naming__five'
|
174
|
+
val = SecureRandom.hex(10)
|
175
|
+
obj.redis_value = val
|
176
|
+
obj.redis_value.should == val
|
177
|
+
obj.redis_value.key.should == 'nested__level_further_naming__five:1:redis_value'
|
178
|
+
obj.redis.get('nested__level_further_naming__five:1:redis_value').should == val
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'verifies that multiple levels do not conflict 3' do
|
182
|
+
module Nested
|
183
|
+
module LevelFurther
|
184
|
+
class NamingFive
|
185
|
+
include Redis::Objects
|
186
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
187
|
+
self.redis_silence_warnings = true
|
188
|
+
|
189
|
+
def id
|
190
|
+
1
|
191
|
+
end
|
192
|
+
|
193
|
+
value :redis_value
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
obj = Nested::LevelFurther::NamingFive.new
|
199
|
+
obj.class.redis_prefix.should == 'nested__level_further__naming_five'
|
200
|
+
val = SecureRandom.hex(10)
|
201
|
+
obj.redis_value = val
|
202
|
+
obj.redis_value.should == val
|
203
|
+
obj.redis_value.key.should == 'nested__level_further__naming_five:1:redis_value'
|
204
|
+
obj.redis.get('nested__level_further__naming_five:1:redis_value').should == val
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'handles dynamically created classes correctly' do
|
208
|
+
module Nested
|
209
|
+
class LevelSix
|
210
|
+
include Redis::Objects
|
211
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
212
|
+
self.redis_silence_warnings = true
|
213
|
+
|
214
|
+
def id
|
215
|
+
1
|
216
|
+
end
|
217
|
+
|
218
|
+
value :redis_value
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
obj = Nested::LevelSix.new
|
223
|
+
obj.class.redis_prefix.should == 'nested__level_six'
|
224
|
+
val = SecureRandom.hex(10)
|
225
|
+
obj.redis_value = val
|
226
|
+
obj.redis_value.should == val
|
227
|
+
obj.redis_value.key.should == 'nested__level_six:1:redis_value'
|
228
|
+
obj.redis.get('nested__level_six:1:redis_value').should == val
|
229
|
+
|
230
|
+
DynamicClass = Class.new(Nested::LevelSix)
|
231
|
+
DynamicClass.value :redis_value2
|
232
|
+
obj2 = DynamicClass.new
|
233
|
+
DynamicClass.redis_prefix.should == 'dynamic_class'
|
234
|
+
obj2.redis_value.should.be.kind_of(Redis::Value)
|
235
|
+
obj2.redis_value2.should.be.kind_of(Redis::Value)
|
236
|
+
obj2.redis_value.key.should == 'dynamic_class:1:redis_value'
|
237
|
+
obj2.redis_value2.key.should == 'dynamic_class:1:redis_value2'
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'handles dynamically created classes correctly in legacy mode' do
|
242
|
+
module Nested
|
243
|
+
class LevelSeven
|
244
|
+
include Redis::Objects
|
245
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
246
|
+
self.redis_legacy_naming = true
|
247
|
+
|
248
|
+
def id
|
249
|
+
1
|
250
|
+
end
|
251
|
+
|
252
|
+
value :redis_value
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
obj = Nested::LevelSeven.new
|
257
|
+
obj.class.redis_prefix.should == 'level_seven'
|
258
|
+
val = SecureRandom.hex(10)
|
259
|
+
obj.redis_value = val
|
260
|
+
obj.redis_value.should == val
|
261
|
+
obj.redis_value.key.should == 'level_seven:1:redis_value'
|
262
|
+
obj.redis.get('level_seven:1:redis_value').should == val
|
263
|
+
|
264
|
+
DynamicClass2 = Class.new(Nested::LevelSeven)
|
265
|
+
DynamicClass2.value :redis_value2
|
266
|
+
obj2 = DynamicClass2.new
|
267
|
+
DynamicClass2.redis_prefix.should == 'dynamic_class2'
|
268
|
+
obj2.redis_value.should.be.kind_of(Redis::Value)
|
269
|
+
obj2.redis_value2.should.be.kind_of(Redis::Value)
|
270
|
+
obj2.redis_value.key.should == 'dynamic_class2:1:redis_value'
|
271
|
+
obj2.redis_value2.key.should == 'dynamic_class2:1:redis_value2'
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'prints a warning message if the key name changes' do
|
275
|
+
module Nested
|
276
|
+
class LevelNine
|
277
|
+
include Redis::Objects
|
278
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
279
|
+
|
280
|
+
def id
|
281
|
+
1
|
282
|
+
end
|
283
|
+
|
284
|
+
value :redis_value
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
captured_output = capture_stderr do
|
289
|
+
# Does not output anything directly.
|
290
|
+
obj = Nested::LevelNine.new
|
291
|
+
val = SecureRandom.hex(10)
|
292
|
+
obj.redis_value = val
|
293
|
+
obj.redis_value.should == val
|
294
|
+
end
|
295
|
+
|
296
|
+
captured_output.should =~ /Warning:/i
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'supports a method to migrate legacy key names' do
|
300
|
+
module Nested
|
301
|
+
class Legacy
|
302
|
+
include Redis::Objects
|
303
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
304
|
+
self.redis_legacy_naming = true
|
305
|
+
|
306
|
+
# override this for testing - need two classes as if we imagine an old and new one
|
307
|
+
# also use the legacy flat prefix that ignores the nested class name
|
308
|
+
self.redis_prefix = 'modern'
|
309
|
+
|
310
|
+
def initialize(id)
|
311
|
+
@id = id
|
312
|
+
end
|
313
|
+
def id
|
314
|
+
@id
|
315
|
+
end
|
316
|
+
|
317
|
+
value :redis_value
|
318
|
+
counter :redis_counter
|
319
|
+
hash_key :redis_hash
|
320
|
+
list :redis_list
|
321
|
+
set :redis_set
|
322
|
+
sorted_set :redis_sorted_set
|
323
|
+
|
324
|
+
# global class counters
|
325
|
+
value :global_value, :global => true
|
326
|
+
counter :global_counter, :global => true
|
327
|
+
hash_key :global_hash_key, :global => true
|
328
|
+
list :global_list, :global => true
|
329
|
+
set :global_set, :global => true
|
330
|
+
sorted_set :global_sorted_set, :global => true
|
331
|
+
|
332
|
+
#callable as key
|
333
|
+
value :global_proc_value, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" }
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
module Nested
|
338
|
+
class Modern
|
339
|
+
include Redis::Objects
|
340
|
+
self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
341
|
+
|
342
|
+
def initialize(id)
|
343
|
+
@id = id
|
344
|
+
end
|
345
|
+
def id
|
346
|
+
@id
|
347
|
+
end
|
348
|
+
|
349
|
+
value :redis_value
|
350
|
+
counter :redis_counter
|
351
|
+
hash_key :redis_hash
|
352
|
+
list :redis_list
|
353
|
+
set :redis_set
|
354
|
+
sorted_set :redis_sorted_set
|
355
|
+
|
356
|
+
# global class counters
|
357
|
+
value :global_value, :global => true
|
358
|
+
counter :global_counter, :global => true
|
359
|
+
hash_key :global_hash_key, :global => true
|
360
|
+
list :global_list, :global => true
|
361
|
+
set :global_set, :global => true
|
362
|
+
sorted_set :global_sorted_set, :global => true
|
363
|
+
|
364
|
+
#callable as key
|
365
|
+
value :global_proc_value, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" }
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# Iterate over them
|
370
|
+
Nested::Modern.redis_objects.length.should == 13
|
371
|
+
Nested::Modern.redis_objects.length.should == Nested::Legacy.redis_objects.length.should
|
372
|
+
Nested::Legacy.redis_prefix.should == 'modern'
|
373
|
+
Nested::Modern.redis_prefix.should == 'nested__modern'
|
374
|
+
|
375
|
+
# Create a whole bunch of keys using the legacy names
|
376
|
+
30.times do |i|
|
377
|
+
# warn i.inspect
|
378
|
+
obj = Nested::Legacy.new(i)
|
379
|
+
obj.redis_value = i
|
380
|
+
obj.redis_value.to_i.should == i
|
381
|
+
obj.redis_counter.increment
|
382
|
+
obj.redis_hash[:key] = i
|
383
|
+
obj.redis_list << i
|
384
|
+
obj.redis_set << i
|
385
|
+
obj.redis_sorted_set[i] = i
|
386
|
+
end
|
387
|
+
|
388
|
+
obj = Nested::Legacy.new(99)
|
389
|
+
obj.global_value = 42
|
390
|
+
obj.global_counter.increment
|
391
|
+
obj.global_counter.increment
|
392
|
+
obj.global_counter.increment
|
393
|
+
obj.global_hash_key[:key] = 'value'
|
394
|
+
obj.global_set << 'a' << 'b'
|
395
|
+
obj.global_sorted_set[:key] = 2.2
|
396
|
+
|
397
|
+
Nested::Modern.migrate_redis_legacy_keys
|
398
|
+
|
399
|
+
# Try to access the keys through modern names now
|
400
|
+
30.times do |i|
|
401
|
+
# warn i.inspect
|
402
|
+
obj = Nested::Modern.new(i)
|
403
|
+
obj.redis_value.to_i.should == i
|
404
|
+
obj.redis_counter.to_i.should == 1
|
405
|
+
obj.redis_hash[:key].to_i.should == i
|
406
|
+
obj.redis_list[0].to_i.should == i
|
407
|
+
obj.redis_set.include?(i).should == true
|
408
|
+
obj.redis_sorted_set[i].should == i
|
409
|
+
end
|
410
|
+
|
411
|
+
obj = Nested::Modern.new(99)
|
412
|
+
obj.global_value.to_i.should == 42
|
413
|
+
obj.global_counter.to_i.should == 3
|
414
|
+
obj.global_hash_key[:key].should == 'value'
|
415
|
+
obj.global_set.should.include?('a').should == true
|
416
|
+
obj.global_set.should.include?('b').should == true
|
417
|
+
obj.global_sorted_set[:key].should == 2.2
|
418
|
+
end
|
419
|
+
end
|
@@ -34,8 +34,8 @@ describe 'Connection tests' do
|
|
34
34
|
obj.redis_value.value.should == nil
|
35
35
|
|
36
36
|
obj.default_redis_value.clear
|
37
|
-
obj.redis_value.value = '
|
38
|
-
obj.redis_value.value.should == '
|
37
|
+
obj.redis_value.value = 'bar'
|
38
|
+
obj.redis_value.value.should == 'bar'
|
39
39
|
obj.default_redis_value.value.should == nil
|
40
40
|
|
41
41
|
obj.redis_value.clear
|
@@ -96,14 +96,9 @@ describe 'Connection tests' do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
it "should support local handles with a vanilla redis connection" do
|
99
|
-
# Redis.current = nil # reset from other tests
|
100
99
|
Redis::Objects.redis = nil
|
101
100
|
@redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
102
|
-
|
103
|
-
# Redis.current is lazily auto-populated to touch 6379
|
104
|
-
# This why we choose the weird 9212 port to avoid
|
105
|
-
# Redis.current.inspect.should == Redis.new.inspect
|
106
|
-
Redis::Objects.redis.inspect.should == Redis.new.inspect
|
101
|
+
raises_exception{ Redis::Objects.redis.inspect } # NotConnected
|
107
102
|
|
108
103
|
v = Redis::Value.new('conn/value', @redis_handle)
|
109
104
|
v.clear
|
@@ -141,14 +136,9 @@ describe 'Connection tests' do
|
|
141
136
|
end
|
142
137
|
|
143
138
|
it "should support local handles with a connection_pool" do
|
144
|
-
# Redis.current = nil # reset from other tests
|
145
139
|
Redis::Objects.redis = nil
|
146
140
|
@redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) }
|
147
|
-
|
148
|
-
# Redis.current is lazily auto-populated to touch 6379
|
149
|
-
# This why we choose the weird 9212 port to avoid
|
150
|
-
# Redis.current.inspect.should == Redis.new.inspect
|
151
|
-
Redis::Objects.redis.inspect.should == Redis.new.inspect
|
141
|
+
raises_exception{ Redis::Objects.redis.inspect } # NotConnected
|
152
142
|
|
153
143
|
v = Redis::Value.new('conn/value', @redis_handle)
|
154
144
|
v.clear
|
@@ -148,7 +148,7 @@ describe Redis::Value do
|
|
148
148
|
end
|
149
149
|
|
150
150
|
it "#{meth} should set expiration when expireat option assigned" do
|
151
|
-
@value = Redis::Value.new('spec/value', :expireat => Time.now + 10
|
151
|
+
@value = Redis::Value.new('spec/value', :expireat => Time.now + 10)
|
152
152
|
@value.send(meth, 'monkey')
|
153
153
|
@value.ttl.should > 0
|
154
154
|
end
|
@@ -286,18 +286,28 @@ describe Redis::List do
|
|
286
286
|
@list.get.should == ['a','c','f','j','h','i','a']
|
287
287
|
end
|
288
288
|
|
289
|
-
it "should support popping
|
289
|
+
it "should support popping and shifting multiple values" do
|
290
290
|
@list.should.be.empty
|
291
291
|
|
292
|
-
@list << 'a' << 'b' << 'c'
|
293
|
-
@list.
|
294
|
-
@list.shift
|
295
|
-
@list.
|
292
|
+
@list << 'a' << 'b' << 'c' << 'd'
|
293
|
+
@list.should == ['a', 'b', 'c', 'd']
|
294
|
+
@list.shift
|
295
|
+
@list.should == ['b', 'c', 'd']
|
296
|
+
@list.shift(2).should == ['b', 'c']
|
297
|
+
@list.should == ['d']
|
298
|
+
@list.shift(2).should == ['d']
|
299
|
+
@list.shift(2).should == nil
|
296
300
|
|
297
|
-
@list << '
|
298
|
-
|
299
|
-
|
300
|
-
@list.pop(2).should == []
|
301
|
+
@list << 'e' << 'f' << 'g'
|
302
|
+
|
303
|
+
# Old behavior
|
304
|
+
# @list.pop(2).should == ['f', 'g']
|
305
|
+
|
306
|
+
# New behavior
|
307
|
+
@list.pop(2).should == ['g', 'f']
|
308
|
+
|
309
|
+
@list.pop(2).should == ['e']
|
310
|
+
@list.pop(2).should == nil
|
301
311
|
end
|
302
312
|
|
303
313
|
it "should handle rpoplpush" do
|
@@ -412,7 +422,7 @@ describe Redis::List do
|
|
412
422
|
end
|
413
423
|
|
414
424
|
it "#{meth} expireat: option" do
|
415
|
-
@list = Redis::List.new('spec/list_exp', :expireat => Time.now + 10
|
425
|
+
@list = Redis::List.new('spec/list_exp', :expireat => Time.now + 10)
|
416
426
|
@list.clear
|
417
427
|
@list.send(meth, 'val')
|
418
428
|
@list.ttl.should > 0
|
@@ -430,7 +440,7 @@ describe Redis::List do
|
|
430
440
|
end
|
431
441
|
|
432
442
|
it "[]= expireat: option" do
|
433
|
-
@list = Redis::List.new('spec/list_exp', :expireat => Time.now + 10
|
443
|
+
@list = Redis::List.new('spec/list_exp', :expireat => Time.now + 10)
|
434
444
|
@list.clear
|
435
445
|
@list.redis.rpush(@list.key, 'hello')
|
436
446
|
@list[0] = 'world'
|
@@ -448,7 +458,7 @@ describe Redis::List do
|
|
448
458
|
end
|
449
459
|
|
450
460
|
it "insert expireat: option" do
|
451
|
-
@list = Redis::List.new('spec/list_exp', :expireat => Time.now + 10
|
461
|
+
@list = Redis::List.new('spec/list_exp', :expireat => Time.now + 10)
|
452
462
|
@list.clear
|
453
463
|
@list.redis.rpush(@list.key, 'hello')
|
454
464
|
@list.insert 'BEFORE', 'hello', 'world'
|
@@ -586,7 +596,7 @@ describe Redis::Counter do
|
|
586
596
|
@counter.ttl.should <= 10
|
587
597
|
end
|
588
598
|
it "expireat: option" do
|
589
|
-
@counter = Redis::Counter.new('spec/counter_exp', :expireat => Time.now + 10
|
599
|
+
@counter = Redis::Counter.new('spec/counter_exp', :expireat => Time.now + 10)
|
590
600
|
@counter.send(meth)
|
591
601
|
@counter.ttl.should > 0
|
592
602
|
@counter.ttl.should <= 10
|
@@ -600,14 +610,14 @@ describe Redis::Counter do
|
|
600
610
|
[:set, :value=].each do |meth|
|
601
611
|
describe meth do
|
602
612
|
it "expiration: option" do
|
603
|
-
@counter = Redis::Counter.new('spec/counter_exp', :expireat => Time.now + 10
|
613
|
+
@counter = Redis::Counter.new('spec/counter_exp', :expireat => Time.now + 10)
|
604
614
|
@counter.send(meth, 99)
|
605
615
|
@counter.should == 99
|
606
616
|
@counter.ttl.should > 0
|
607
617
|
@counter.ttl.should <= 10
|
608
618
|
end
|
609
619
|
it "expireat: option" do
|
610
|
-
@counter = Redis::Counter.new('spec/counter_exp', :expireat => Time.now + 10
|
620
|
+
@counter = Redis::Counter.new('spec/counter_exp', :expireat => Time.now + 10)
|
611
621
|
@counter.send(meth, 99)
|
612
622
|
@counter.should == 99
|
613
623
|
@counter.ttl.should > 0
|
@@ -805,22 +815,25 @@ end
|
|
805
815
|
describe Redis::HashKey do
|
806
816
|
describe "With Marshal" do
|
807
817
|
before do
|
808
|
-
@hash = Redis::HashKey.new('test_hash', {:marshal_keys=>{'created_at'=>true}})
|
818
|
+
@hash = Redis::HashKey.new('test_hash', {:marshal_keys=>{'created_at' => true}})
|
809
819
|
@hash.clear
|
810
820
|
end
|
811
821
|
|
812
822
|
it "should marshal specified keys" do
|
813
|
-
|
823
|
+
time = Time.now
|
824
|
+
@hash['created_at'] = time
|
825
|
+
@hash['created_at'].should == time
|
814
826
|
@hash['created_at'].class.should == Time
|
815
827
|
end
|
816
828
|
|
817
829
|
it "should not marshal unless required" do
|
818
|
-
@hash['updated_at'] =
|
830
|
+
@hash['updated_at'] = 10
|
831
|
+
@hash['updated_at'].should == "10"
|
819
832
|
@hash['updated_at'].class.should == String
|
820
833
|
end
|
821
834
|
|
822
835
|
it "should marshall appropriate key with bulk set and get" do
|
823
|
-
@hash.bulk_set({'created_at'=>Time.now, 'updated_at'=>
|
836
|
+
@hash.bulk_set({'created_at' => Time.now, 'updated_at' => 11})
|
824
837
|
|
825
838
|
@hash['created_at'].class.should == Time
|
826
839
|
@hash['updated_at'].class.should == String
|
@@ -849,7 +862,7 @@ describe Redis::HashKey do
|
|
849
862
|
# no marshaling
|
850
863
|
@hash.options[:marshal] = false
|
851
864
|
v = {:json => 'data'}
|
852
|
-
@hash['abc'] = v
|
865
|
+
@hash['abc'] = v.to_s
|
853
866
|
@hash['abc'].should == v.to_s
|
854
867
|
|
855
868
|
@hash.options[:marshal] = true
|
@@ -1075,7 +1088,7 @@ describe Redis::HashKey do
|
|
1075
1088
|
end
|
1076
1089
|
|
1077
1090
|
it "#{meth} expireat: option" do
|
1078
|
-
@hash = Redis::HashKey.new('spec/hash_expireat', :expireat => Time.now + 10
|
1091
|
+
@hash = Redis::HashKey.new('spec/hash_expireat', :expireat => Time.now + 10)
|
1079
1092
|
@hash.clear
|
1080
1093
|
@hash.send(meth, *args)
|
1081
1094
|
@hash.ttl.should > 0
|
@@ -1294,7 +1307,7 @@ describe Redis::Set do
|
|
1294
1307
|
end
|
1295
1308
|
|
1296
1309
|
it "should set expiration when expireat option assigned" do
|
1297
|
-
@set = Redis::Set.new('spec/set', :expireat => Time.now + 10
|
1310
|
+
@set = Redis::Set.new('spec/set', :expireat => Time.now + 10)
|
1298
1311
|
@set.send(meth, 'val')
|
1299
1312
|
@set.ttl.should > 0
|
1300
1313
|
@set.ttl.should <= 10
|
@@ -1558,7 +1571,7 @@ describe Redis::SortedSet do
|
|
1558
1571
|
end
|
1559
1572
|
|
1560
1573
|
it 'should set expiration when expireat option assigned' do
|
1561
|
-
@set = Redis::SortedSet.new('spec/zset', :expireat => Time.now + 10
|
1574
|
+
@set = Redis::SortedSet.new('spec/zset', :expireat => Time.now + 10)
|
1562
1575
|
@set['val'] = 1
|
1563
1576
|
@set.ttl.should > 0
|
1564
1577
|
@set.ttl.should <= 10
|
@@ -1590,7 +1603,7 @@ describe Redis::SortedSet do
|
|
1590
1603
|
@set.ttl.should <= 10
|
1591
1604
|
end
|
1592
1605
|
it "#{meth} expireat: option" do
|
1593
|
-
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10
|
1606
|
+
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10)
|
1594
1607
|
@set.clear
|
1595
1608
|
@set.send(meth, 'somekey', 12)
|
1596
1609
|
@set.ttl.should > 0
|
@@ -1607,7 +1620,7 @@ describe Redis::SortedSet do
|
|
1607
1620
|
@set.ttl.should <= 10
|
1608
1621
|
end
|
1609
1622
|
it "#{meth} expireat: option" do
|
1610
|
-
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10
|
1623
|
+
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10)
|
1611
1624
|
@set.clear
|
1612
1625
|
@set.send(meth, 'somekey' => 12)
|
1613
1626
|
@set.ttl.should > 0
|
@@ -1626,7 +1639,7 @@ describe Redis::SortedSet do
|
|
1626
1639
|
end
|
1627
1640
|
|
1628
1641
|
it "#{meth} expireat: option" do
|
1629
|
-
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10
|
1642
|
+
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10)
|
1630
1643
|
@set.clear
|
1631
1644
|
@set.redis.zadd(@set.key, 1, "1")
|
1632
1645
|
@set.send(meth, 'sets', Redis::SortedSet.new('other'))
|
@@ -1646,7 +1659,7 @@ describe Redis::SortedSet do
|
|
1646
1659
|
end
|
1647
1660
|
|
1648
1661
|
it "delete expireat: option" do
|
1649
|
-
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10
|
1662
|
+
@set = Redis::SortedSet.new('spec/zset_exp', :expireat => Time.now + 10)
|
1650
1663
|
@set.clear
|
1651
1664
|
@set.redis.zadd(@set.key, 1, "1")
|
1652
1665
|
@set.redis.zadd(@set.key, 2, "2")
|
@@ -10,18 +10,18 @@ class Roster
|
|
10
10
|
counter :pitchers, :limit => :max_pitchers
|
11
11
|
counter :basic
|
12
12
|
hash_key :contact_information, :marshal_keys=>{'updated_at'=>true}
|
13
|
-
|
13
|
+
redis_lock :resort, :timeout => 2
|
14
14
|
value :starting_pitcher, :marshal => true
|
15
15
|
list :player_stats, :marshal => true
|
16
16
|
set :outfielders, :marshal => true
|
17
17
|
sorted_set :rank
|
18
|
-
|
18
|
+
redis_lock :per_field
|
19
19
|
|
20
20
|
# global class counters
|
21
21
|
counter :total_players_online, :global => true
|
22
22
|
set :all_players_online, :global => true
|
23
23
|
value :last_player, :global => true
|
24
|
-
|
24
|
+
redis_lock :nasty_global_mutex, :global => true # remember it appends "_lock"
|
25
25
|
sorted_set :global_player_leaderboard, :global => true
|
26
26
|
hash_key :global_player_online_status, :global => true
|
27
27
|
|
@@ -966,9 +966,13 @@ describe Redis::Objects do
|
|
966
966
|
end
|
967
967
|
|
968
968
|
it "should pick up class methods from superclass automatically" do
|
969
|
+
Roster.redis_prefix.should == 'roster'
|
969
970
|
CounterRoster = Class.new(Roster)
|
971
|
+
CounterRoster.redis_prefix.should == 'counter_roster'
|
970
972
|
CounterRoster.counter :extended_counter
|
971
973
|
extended_roster = CounterRoster.new
|
974
|
+
Roster.redis_prefix.should == 'roster'
|
975
|
+
extended_roster.class.redis_prefix.should == 'counter_roster'
|
972
976
|
extended_roster.basic.should.be.kind_of(Redis::Counter)
|
973
977
|
extended_roster.extended_counter.should.be.kind_of(Redis::Counter)
|
974
978
|
@roster.respond_to?(:extended_counter).should == false
|
@@ -981,7 +985,7 @@ describe Redis::Objects do
|
|
981
985
|
@roster.respond_to?(:extended_hash_key).should == false
|
982
986
|
|
983
987
|
LockRoster = Class.new(Roster)
|
984
|
-
LockRoster.
|
988
|
+
LockRoster.redis_lock :extended
|
985
989
|
extended_roster = LockRoster.new
|
986
990
|
extended_roster.resort_lock.should.be.kind_of(Redis::Lock)
|
987
991
|
extended_roster.extended_lock.should.be.kind_of(Redis::Lock)
|
data/spec/spec_helper.rb
CHANGED
@@ -10,7 +10,7 @@ if $0 =~ /\brspec$/
|
|
10
10
|
end
|
11
11
|
|
12
12
|
# For the incompatible change from redis.rb
|
13
|
-
Redis.exists_returns_integer = true
|
13
|
+
# Redis.exists_returns_integer = true
|
14
14
|
|
15
15
|
# Avoid phantom remote test failures
|
16
16
|
RUNNING_LOCALLY = !ENV['TRAVIS']
|
@@ -61,7 +61,7 @@ def kill_redis
|
|
61
61
|
Process.kill "TERM", pid
|
62
62
|
Process.kill "KILL", pid
|
63
63
|
File.unlink pidfile
|
64
|
-
File.unlink rdbfile if File.
|
64
|
+
File.unlink rdbfile if File.exist? rdbfile
|
65
65
|
end
|
66
66
|
|
67
67
|
# Start redis-server except under JRuby
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-objects
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Wiger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '5.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '5.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,6 +188,7 @@ files:
|
|
188
188
|
- lib/redis/value.rb
|
189
189
|
- redis-objects.gemspec
|
190
190
|
- spec/redis_autoload_objects_spec.rb
|
191
|
+
- spec/redis_legacy_key_naming_spec.rb
|
191
192
|
- spec/redis_namespace_compat_spec.rb
|
192
193
|
- spec/redis_objects_active_record_spec.rb
|
193
194
|
- spec/redis_objects_conn_spec.rb
|
@@ -210,16 +211,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
210
211
|
version: '0'
|
211
212
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
212
213
|
requirements:
|
213
|
-
- - "
|
214
|
+
- - ">"
|
214
215
|
- !ruby/object:Gem::Version
|
215
|
-
version:
|
216
|
+
version: 1.3.1
|
216
217
|
requirements: []
|
217
|
-
rubygems_version: 3.
|
218
|
+
rubygems_version: 3.4.10
|
218
219
|
signing_key:
|
219
220
|
specification_version: 4
|
220
221
|
summary: Map Redis types directly to Ruby objects
|
221
222
|
test_files:
|
222
223
|
- spec/redis_autoload_objects_spec.rb
|
224
|
+
- spec/redis_legacy_key_naming_spec.rb
|
223
225
|
- spec/redis_namespace_compat_spec.rb
|
224
226
|
- spec/redis_objects_active_record_spec.rb
|
225
227
|
- spec/redis_objects_conn_spec.rb
|