redis-namespace 0.2.1 → 0.3.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.

Potentially problematic release.


This version of redis-namespace might be problematic. Click here for more details.

Files changed (4) hide show
  1. data/Rakefile +4 -4
  2. data/lib/redis/namespace.rb +158 -110
  3. data/spec/redis_spec.rb +66 -1
  4. metadata +2 -2
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  task :default => :spec
2
- task :test => :spec
2
+ task :test => :spec
3
3
 
4
4
  desc "Run specs"
5
5
  task :spec do
@@ -15,10 +15,10 @@ begin
15
15
  gemspec.email = "chris@ozmm.org"
16
16
  gemspec.homepage = "http://github.com/defunkt/redis-namespace"
17
17
  gemspec.authors = ["Chris Wanstrath"]
18
- gemspec.version = '0.2.1'
18
+ gemspec.version = '0.3.0'
19
19
  gemspec.add_dependency 'redis'
20
20
  end
21
21
  rescue LoadError
22
- puts "Jeweler not available. Install it with:"
23
- puts "gem install jeweler"
22
+ warn "Jeweler not available. Install it with:"
23
+ warn "gem install jeweler"
24
24
  end
@@ -2,86 +2,120 @@ require 'redis'
2
2
 
3
3
  class Redis
4
4
  class Namespace
5
- # Generated from http://code.google.com/p/redis/wiki/CommandReference
6
- # using the following jQuery:
5
+ # The following table defines how input parameters and result
6
+ # values should be modified for the namespace.
7
7
  #
8
- # $('.vt li a').map(function(i,e){return $(e).text().toLowerCase()}).sort().toArray()
9
- COMMANDS = [
10
- "auth",
11
- "bgrewriteaof",
12
- "bgsave",
13
- "blpop",
14
- "brpop",
15
- "dbsize",
16
- "decr",
17
- "decrby",
18
- "del",
19
- "exists",
20
- "expire",
21
- "flushall",
22
- "flushdb",
23
- "get",
24
- "getset",
25
- "incr",
26
- "incrby",
27
- "info",
28
- "keys",
29
- "lastsave",
30
- "lindex",
31
- "llen",
32
- "lpop",
33
- "lpush",
34
- "lrange",
35
- "lrem",
36
- "lset",
37
- "ltrim",
38
- "mget",
39
- "monitor",
40
- "move",
41
- "mset",
42
- "msetnx",
43
- "quit",
44
- "randomkey",
45
- "rename",
46
- "renamenx",
47
- "rpop",
48
- "rpoplpush",
49
- "rpush",
50
- "sadd",
51
- "save",
52
- "scard",
53
- "sdiff",
54
- "sdiffstore",
55
- "select",
56
- "set",
57
- "setnx",
58
- "shutdown",
59
- "sinter",
60
- "sinterstore",
61
- "sismember",
62
- "slaveof",
63
- "smembers",
64
- "smove",
65
- "sort",
66
- "spop",
67
- "srandmember",
68
- "srem",
69
- "sunion",
70
- "sunionstore",
71
- "ttl",
72
- "type",
73
- "zadd",
74
- "zcard",
75
- "zincrby",
76
- "zrange",
77
- "zrangebyscore",
78
- "zrem",
79
- "zremrangebyscore",
80
- "zrevrange",
81
- "zscore",
82
- "[]",
83
- "[]="
84
- ]
8
+ # COMMANDS is a hash. Each key is the name of a command and each
9
+ # value is a two element array.
10
+ #
11
+ # The first element in the value array describes how to modify the
12
+ # arguments passed. It can be one of:
13
+ #
14
+ # nil
15
+ # Do nothing.
16
+ # :first
17
+ # Add the namespace to the first argument passed, e.g.
18
+ # GET key => GET namespace:key
19
+ # :all
20
+ # Add the namespace to all arguments passed, e.g.
21
+ # MGET key1 key2 => MGET namespace:key1 namespace:key2
22
+ # :exclude_first
23
+ # Add the namespace to all arguments but the first, e.g.
24
+ # :exclude_last
25
+ # Add the namespace to all arguments but the last, e.g.
26
+ # BLPOP key1 key2 timeout =>
27
+ # BLPOP namespace:key1 namespace:key2 timeout
28
+ # :alternate
29
+ # Add the namespace to every other argument, e.g.
30
+ # MSET key1 value1 key2 value2 =>
31
+ # MSET namespace:key1 value1 namespace:key2 value2
32
+ #
33
+ # The second element in the value array describes how to modify
34
+ # the return value of the Redis call. It can be one of:
35
+ #
36
+ # nil
37
+ # Do nothing.
38
+ # :all
39
+ # Add the namespace to all elements returned, e.g.
40
+ # key1 key2 => namespace:key1 namespace:key2
41
+ COMMANDS = {
42
+ "auth" => [],
43
+ "bgrewriteaof" => [],
44
+ "bgsave" => [],
45
+ "blpop" => [ :exclude_last ],
46
+ "brpop" => [ :exclude_last ],
47
+ "dbsize" => [],
48
+ "decr" => [ :first ],
49
+ "decrby" => [ :first ],
50
+ "del" => [ :all ],
51
+ "exists" => [ :first ],
52
+ "expire" => [ :first ],
53
+ "flushall" => [],
54
+ "flushdb" => [],
55
+ "get" => [ :first ],
56
+ "getset" => [ :first ],
57
+ "incr" => [ :first ],
58
+ "incrby" => [ :first ],
59
+ "info" => [],
60
+ "keys" => [ :first, :all ],
61
+ "lastsave" => [],
62
+ "lindex" => [ :first ],
63
+ "llen" => [ :first ],
64
+ "lpop" => [ :first ],
65
+ "lpush" => [ :first ],
66
+ "lrange" => [ :first ],
67
+ "lrem" => [ :first ],
68
+ "lset" => [ :first ],
69
+ "ltrim" => [ :first ],
70
+ "mapped_mget" => [ :all, :all ],
71
+ "mget" => [ :all ],
72
+ "monitor" => [ :monitor ],
73
+ "move" => [ :first ],
74
+ "mset" => [ :alternate ],
75
+ "msetnx" => [ :alternate ],
76
+ "quit" => [],
77
+ "randomkey" => [],
78
+ "rename" => [ :all ],
79
+ "renamenx" => [ :all ],
80
+ "rpop" => [ :first ],
81
+ "rpoplpush" => [ :all ],
82
+ "rpush" => [ :first ],
83
+ "sadd" => [ :first ],
84
+ "save" => [],
85
+ "scard" => [ :first ],
86
+ "sdiff" => [ :all ],
87
+ "sdiffstore" => [ :all ],
88
+ "select" => [],
89
+ "set" => [ :first ],
90
+ "setnx" => [ :first ],
91
+ "shutdown" => [],
92
+ "sinter" => [ :all ],
93
+ "sinterstore" => [ :all ],
94
+ "sismember" => [ :first ],
95
+ "slaveof" => [],
96
+ "smembers" => [ :first ],
97
+ "smove" => [ :exclude_last ],
98
+ "sort" => [ :sort ],
99
+ "spop" => [ :first ],
100
+ "srandmember" => [ :first ],
101
+ "srem" => [ :first ],
102
+ "sunion" => [ :all ],
103
+ "sunionstore" => [ :all ],
104
+ "ttl" => [ :first ],
105
+ "type" => [ :first ],
106
+ "zadd" => [ :first ],
107
+ "zcard" => [ :first ],
108
+ "zincrby" => [ :first ],
109
+ "zrange" => [ :first ],
110
+ "zrangebyscore" => [ :first ],
111
+ "zrem" => [ :first ],
112
+ "zremrangebyscore" => [ :first ],
113
+ "zrevrange" => [ :first ],
114
+ "zscore" => [ :first ],
115
+ "[]" => [ :first ],
116
+ "[]=" => [ :first ]
117
+ }
118
+
85
119
 
86
120
  attr_accessor :namespace
87
121
 
@@ -96,48 +130,62 @@ class Redis
96
130
  method_missing(:type, key)
97
131
  end
98
132
 
99
- def mapped_mget(*keys)
100
- result = {}
101
- mget(*keys).each do |value|
102
- key = keys.shift
103
- result.merge!(key => value) unless value.nil?
133
+ def method_missing(command, *args, &block)
134
+ (before, after) = COMMANDS[command.to_s] ||
135
+ COMMANDS[Redis::ALIASES[command.to_s]]
136
+
137
+ # Add the namespace to any parameters that are keys.
138
+ case before
139
+ when :first
140
+ args[0] = add_namespace(args[0]) if args[0]
141
+ when :all
142
+ args = add_namespace(args)
143
+ when :exclude_first
144
+ first = args.shift
145
+ args = add_namespace(args)
146
+ args.unshift(first) if first
147
+ when :exclude_last
148
+ last = args.pop
149
+ args = add_namespace(args)
150
+ args.push(last) if last
151
+ when :alternate
152
+ args = [ add_namespace(Hash[*args]) ]
104
153
  end
105
- result
106
- end
107
154
 
108
- def mget(*keys)
109
- keys = keys.map { |key| "#{@namespace}:#{key}"} if @namespace
110
- call_command([:mget] + keys)
111
- end
155
+ # Dispatch the command to Redis and store the result.
156
+ result = @redis.send(command, *args, &block)
112
157
 
113
- def mset(keys)
114
- call_mset(:mset, keys)
115
- end
158
+ # Remove the namespace from results that are keys.
159
+ result = rem_namespace(result) if after == :all
116
160
 
117
- def msetnx(keys)
118
- call_mset(:msetnx, keys)
161
+ result
119
162
  end
120
163
 
121
- def method_missing(command, *args, &block)
122
- if COMMANDS.include?(command.to_s) && args[0]
123
- args[0] = "#{@namespace}:#{args[0]}"
124
- end
164
+ private
165
+ def add_namespace(key)
166
+ return key unless key && @namespace
125
167
 
126
- @redis.send(command, *args, &block)
168
+ case key
169
+ when Array
170
+ key.map {|k| add_namespace k}
171
+ when Hash
172
+ Hash[*key.map {|k, v| [ add_namespace(k), v ]}.flatten]
173
+ else
174
+ "#{@namespace}:#{key}"
175
+ end
127
176
  end
128
177
 
178
+ def rem_namespace(key)
179
+ return key unless key && @namespace
129
180
 
130
- private
131
-
132
-
133
- def call_mset(command, keys)
134
- if @namespace
135
- namespaced_keys = {}
136
- keys.each { |key, value| namespaced_keys["#{@namespace}:#{key}"] = value }
137
- keys = namespaced_keys
181
+ case key
182
+ when Array
183
+ key.map {|k| rem_namespace k}
184
+ when Hash
185
+ Hash[*key.map {|k, v| [ rem_namespace(k), v ]}.flatten]
186
+ else
187
+ key.to_s.gsub /^#{@namespace}:/, ""
138
188
  end
139
-
140
- call_command([command] + [keys])
141
189
  end
142
190
  end
143
191
  end
data/spec/redis_spec.rb CHANGED
@@ -6,10 +6,10 @@ describe "redis" do
6
6
  before(:all) do
7
7
  # use database 15 for testing so we dont accidentally step on you real data
8
8
  @redis = Redis.new :db => 15
9
- @namespaced = Redis::Namespace.new(:ns, :redis => @redis)
10
9
  end
11
10
 
12
11
  before(:each) do
12
+ @namespaced = Redis::Namespace.new(:ns, :redis => @redis)
13
13
  @namespaced.flushdb
14
14
  @redis['foo'] = 'bar'
15
15
  end
@@ -35,6 +35,17 @@ describe "redis" do
35
35
  @namespaced.type('counter').should == 'string'
36
36
  end
37
37
 
38
+ it "should be able to use a namespace with del" do
39
+ @namespaced['foo'] = 1000
40
+ @namespaced['bar'] = 2000
41
+ @namespaced['baz'] = 3000
42
+ @namespaced.del 'foo'
43
+ @namespaced['foo'].should == nil
44
+ @namespaced.del 'bar', 'baz'
45
+ @namespaced['bar'].should == nil
46
+ @namespaced['baz'].should == nil
47
+ end
48
+
38
49
  it "should be able to use a namespace with mget" do
39
50
  @namespaced['foo'] = 1000
40
51
  @namespaced['bar'] = 2000
@@ -54,6 +65,33 @@ describe "redis" do
54
65
  @namespaced.mapped_mget('foo', 'baz', 'bar').should == { 'foo' => '1000', 'bar' => '2000'}
55
66
  end
56
67
 
68
+ it "should properly intersect three sets" do
69
+ @namespaced.sadd('foo', 1)
70
+ @namespaced.sadd('foo', 2)
71
+ @namespaced.sadd('foo', 3)
72
+ @namespaced.sadd('bar', 2)
73
+ @namespaced.sadd('bar', 3)
74
+ @namespaced.sadd('bar', 4)
75
+ @namespaced.sadd('baz', 3)
76
+ @namespaced.sinter('foo', 'bar', 'baz').should == %w( 3 )
77
+ end
78
+
79
+ it "should properly union two sets" do
80
+ @namespaced.sadd('foo', 1)
81
+ @namespaced.sadd('foo', 2)
82
+ @namespaced.sadd('bar', 2)
83
+ @namespaced.sadd('bar', 3)
84
+ @namespaced.sadd('bar', 4)
85
+ @namespaced.sunion('foo', 'bar').sort.should == %w( 1 2 3 4 )
86
+ end
87
+
88
+ it "should yield the correct list of keys" do
89
+ @namespaced["foo"] = 1
90
+ @namespaced["bar"] = 2
91
+ @namespaced["baz"] = 3
92
+ @namespaced.keys("*").sort.should == %w( bar baz foo )
93
+ end
94
+
57
95
  it "can change its namespace" do
58
96
  @namespaced['foo'].should == nil
59
97
  @namespaced['foo'] = 'chris'
@@ -67,4 +105,31 @@ describe "redis" do
67
105
  @namespaced['foo'] = 'chris'
68
106
  @namespaced['foo'].should == 'chris'
69
107
  end
108
+
109
+ it "should support command aliases (delete)" do
110
+ @namespaced.delete('foo')
111
+ @redis.should_not have_key('ns:foo')
112
+ end
113
+
114
+ it "should support command aliases (set_add)" do
115
+ @namespaced.set_add('bar', 'quux')
116
+ @namespaced.smembers('bar').should include('quux')
117
+ end
118
+
119
+ it "should support command aliases (push_head)" do
120
+ @namespaced.push_head('bar', 'quux')
121
+ @redis.llen('ns:bar').should == 1
122
+ end
123
+
124
+ it "should support command aliases (zset_add)" do
125
+ @namespaced.zset_add('bar', 1, 'quux')
126
+ @redis.zcard('ns:bar').should == 1
127
+ end
128
+
129
+
130
+ Spec::Matchers.define :have_key do |expected|
131
+ match do |redis|
132
+ redis.exists(expected)
133
+ end
134
+ end
70
135
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-namespace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-16 00:00:00 -08:00
12
+ date: 2010-03-12 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency