redis_wrapper 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -0,0 +1,3 @@
1
+ # Redis Wrapper
2
+
3
+ Redis Wrapper is built on top of the [redis-rb](https://github.com/ezmobius/redis-rb) library as a communication method between ruby code and redis. Redis-rb handles all the connection to the database store, while redis_wrapper supplies a more convient interface on which to communicate. All methods available via redis-rb are accessible by the wrapper, but allows objects other than strings to be passed in.
@@ -1,17 +1,170 @@
1
1
  module RedisWrapper
2
2
  class RedisWrapper
3
+ attr_accessor :namespace
4
+ # The following table defines how input parameters and result
5
+ # values should be modified for the namespace along with Object compression.
6
+ # Thanks is due to defunkt and his gem, https://github.com/defunkt/redis-namespace as
7
+ # inspiration on how to solve this problem.
8
+ #
9
+ # COMMANDS is a hash. Each key is the name of a command and each
10
+ # value is a hash itself. The namespace key holds an 2 value array, determining the process of
11
+ # how to merge on the namespace. The options key, holds a hash that is merged onto the other options passed
12
+ # This insures that some commands like AUTH, are enforced to be raw true so Entry doesn't alter the command.
13
+ #
14
+ # The first element in the value array describes how to modify the
15
+ # arguments passed. It can be one of:
16
+ #
17
+ # nil
18
+ # Do nothing.
19
+ # :first
20
+ # Add the namespace to the first argument passed, e.g.
21
+ # GET key => GET namespace:key
22
+ # :all
23
+ # Add the namespace to all arguments passed, e.g.
24
+ # MGET key1 key2 => MGET namespace:key1 namespace:key2
25
+ # :exclude_first
26
+ # Add the namespace to all arguments but the first, e.g.
27
+ # :exclude_last
28
+ # Add the namespace to all arguments but the last, e.g.
29
+ # BLPOP key1 key2 timeout =>
30
+ # BLPOP namespace:key1 namespace:key2 timeout
31
+ # :exclude_options
32
+ # Add the namespace to all arguments, except the last argument,
33
+ # if the last argument is a hash of options.
34
+ # ZUNIONSTORE key1 2 key2 key3 WEIGHTS 2 1 =>
35
+ # ZUNIONSTORE namespace:key1 2 namespace:key2 namespace:key3 WEIGHTS 2 1
36
+ # :alternate
37
+ # Add the namespace to every other argument, e.g.
38
+ # MSET key1 value1 key2 value2 =>
39
+ # MSET namespace:key1 value1 namespace:key2 value2
40
+ #
41
+ # The second element in the value array describes how to modify
42
+ # the return value of the Redis call. It can be one of:
43
+ #
44
+ # nil
45
+ # Do nothing.
46
+ # :all
47
+ # Add the namespace to all elements returned, e.g.
48
+ # key1 key2 => namespace:key1 namespace:key2
49
+ COMMANDS = {
50
+ :auth => {:namespace=>[],:options=>{:raw=>true}},
51
+ :bgrewriteaof => {:namespace=>[], :options=>{}},
52
+ :bgsave => {:namespace=>[], :options=>{}},
53
+ :blpop => {:namespace=>[ :exclude_last, :first ], :options=>{}},
54
+ :brpop => {:namespace=>[ :exclude_last ], :options=>{}},
55
+ :dbsize => {:namespace=>[], :options=>{}},
56
+ :debug => {:namespace=>[ :exclude_first ], :options=>{}},
57
+ :decr => {:namespace=>[ :first ], :options=>{}},
58
+ :decrby => {:namespace=>[ :first ], :options=>{}},
59
+ :del => {:namespace=>[ :all ], :options=>{}},
60
+ :exists => {:namespace=>[ :first ], :options=>{}},
61
+ :expire => {:namespace=>[ :first ], :options=>{}},
62
+ :expireat => {:namespace=>[ :first ], :options=>{}},
63
+ :flushall => {:namespace=>[], :options=>{}},
64
+ :flushdb => {:namespace=>[], :options=>{}},
65
+ :get => {:namespace=>[ :first ], :options=>{}},
66
+ :getset => {:namespace=>[ :first ], :options=>{}},
67
+ :hset => {:namespace=>[ :first ], :options=>{}},
68
+ :hsetnx => {:namespace=>[ :first ], :options=>{}},
69
+ :hget => {:namespace=>[ :first ], :options=>{}},
70
+ :hincrby => {:namespace=>[ :first ], :options=>{}},
71
+ :hmget => {:namespace=>[ :first ], :options=>{}},
72
+ :hmset => {:namespace=>[ :first ], :options=>{}},
73
+ :hdel => {:namespace=>[ :first ], :options=>{}},
74
+ :hexists => {:namespace=>[ :first ], :options=>{}},
75
+ :hlen => {:namespace=>[ :first ], :options=>{}},
76
+ :hkeys => {:namespace=>[ :first ], :options=>{}},
77
+ :hvals => {:namespace=>[ :first ], :options=>{}},
78
+ :hgetall => {:namespace=>[ :first ], :options=>{}},
79
+ :incr => {:namespace=>[ :first ], :options=>{}},
80
+ :incrby => {:namespace=>[ :first ], :options=>{}},
81
+ :info => {:namespace=>[], :options=>{}},
82
+ :keys => {:namespace=>[ :first, :all ], :options=>{}},
83
+ :lastsave => {:namespace=>[], :options=>{}},
84
+ :lindex => {:namespace=>[ :first ], :options=>{}},
85
+ :llen => {:namespace=>[ :first ], :options=>{}},
86
+ :lpop => {:namespace=>[ :first ], :options=>{}},
87
+ :lpush => {:namespace=>[ :first ], :options=>{}},
88
+ :lrange => {:namespace=>[ :first ], :options=>{}},
89
+ :lrem => {:namespace=>[ :first ], :options=>{}},
90
+ :lset => {:namespace=>[ :first ], :options=>{}},
91
+ :ltrim => {:namespace=>[ :first ], :options=>{}},
92
+ :mapped_hmset => {:namespace=>[ :first ], :options=>{}},
93
+ :mapped_mget => {:namespace=>[ :all, :all ], :options=>{}},
94
+ :mget => {:namespace=>[ :all ], :options=>{}},
95
+ #:monitor => {:namespace=>[ :monitor ], :options=>{}},
96
+ :move => {:namespace=>[ :first ], :options=>{}},
97
+ :mset => {:namespace=>[ :alternate ], :options=>{}},
98
+ :msetnx => {:namespace=>[ :alternate ], :options=>{}},
99
+ :psubscribe => {:namespace=>[ :all ], :options=>{}},
100
+ :publish => {:namespace=>[ :first ], :options=>{}},
101
+ :punsubscribe => {:namespace=>[ :all ], :options=>{}},
102
+ :quit => {:namespace=>[], :options=>{}},
103
+ :randomkey => {:namespace=>[], :options=>{}},
104
+ :rename => {:namespace=>[ :all ], :options=>{}},
105
+ :renamenx => {:namespace=>[ :all ], :options=>{}},
106
+ :rpop => {:namespace=>[ :first ], :options=>{}},
107
+ :rpoplpush => {:namespace=>[ :all ], :options=>{}},
108
+ :rpush => {:namespace=>[ :first ], :options=>{}},
109
+ :sadd => {:namespace=>[ :first ], :options=>{}},
110
+ :save => {:namespace=>[], :options=>{}},
111
+ :scard => {:namespace=>[ :first ], :options=>{}},
112
+ :sdiff => {:namespace=>[ :all ], :options=>{}},
113
+ :sdiffstore => {:namespace=>[ :all ], :options=>{}},
114
+ :select => {:namespace=>[], :options=>{}},
115
+ :set => {:namespace=>[ :first ], :options=>{}},
116
+ :setex => {:namespace=>[ :first ], :options=>{}},
117
+ :setnx => {:namespace=>[ :first ], :options=>{}},
118
+ :shutdown => {:namespace=>[], :options=>{}},
119
+ :sinter => {:namespace=>[:all], :options=>{}},
120
+ :sinterstore => {:namespace=>[:all], :options=>{}},
121
+ :sismember => {:namespace=>[:first], :options=>{}},
122
+ :slaveof => {:namespace=>[], :options=>{}},
123
+ :smembers => {:namespace=>[:first], :options=>{}},
124
+ :smove => {:namespace=>[:exclude_last], :options=>{}},
125
+ #:sort => {:namespace=>[:sort], :options=>{}},
126
+ :spop => {:namespace=>[:first], :options=>{}},
127
+ :srandmember => {:namespace=>[:first], :options=>{}},
128
+ :srem => {:namespace=>[:first], :options=>{}},
129
+ :subscribe => {:namespace=>[:all], :options=>{}},
130
+ :sunion => {:namespace=>[:all], :options=>{}},
131
+ :sunionstore => {:namespace=>[:all], :options=>{}},
132
+ :ttl => {:namespace=>[:first], :options=>{}},
133
+ :type => {:namespace=>[:first], :options=>{}},
134
+ :unsubscribe => {:namespace=>[:all], :options=>{}},
135
+ :zadd => {:namespace=>[:first], :options=>{}},
136
+ :zcard => {:namespace=>[:first], :options=>{}},
137
+ :zcount => {:namespace=>[:first], :options=>{}},
138
+ :zincrby => {:namespace=>[:first], :options=>{}},
139
+ :zinterstore => {:namespace=>[:exclude_options],:options=>{}},
140
+ :zrange => {:namespace=>[:first], :options=>{}},
141
+ :zrangebyscore => {:namespace=>[:first], :options=>{}},
142
+ :zrank => {:namespace=>[:first], :options=>{}},
143
+ :zrem => {:namespace=>[:first], :options=>{}},
144
+ :zremrangebyrank => {:namespace=>[:first], :options=>{}},
145
+ :zremrangebyscore => {:namespace=>[:first], :options=>{}},
146
+ :zrevrange => {:namespace=>[:first], :options=>{}},
147
+ :zrevrangebyscore => {:namespace=>[:first], :options=>{}},
148
+ :zrevrank => {:namespace=>[:first], :options=>{}},
149
+ :zscore => {:namespace=>[:first], :options=>{}},
150
+ :zunionstore => {:namespace=>[:exclude_options], :options=>{}},
151
+ :[] => {:namespace=>[:first], :options=>{}},
152
+ :[]= => {:namespace=>[:first], :options=>{}}
153
+ }
154
+
3
155
  def initialize(options={})
4
- @client = Redis.new(options)
156
+ @namespace = options[:namespace]
157
+ @client = options[:redis] || Redis.current
5
158
  end
159
+
6
160
  def method_missing(method, *args, &block)
7
161
  if @client.respond_to? method
8
- options, args = get_options(*args) || [{}, args]
9
- key, args = get_key(*args)
10
- args = handle(*args)
11
- args = [key] + args if args && key
12
- result = Entry.new(@client.send(method, *args, &block), options).extracted_result
13
- @client.send(:expire, key, options[:expire_in].to_i) if options[:expire_in]
14
- result
162
+ @options, args = get_options(*args) || [{}, args]
163
+ @options.merge(COMMANDS[method.to_sym][:options])
164
+ args = handle(method, *args)
165
+ result = @client.send(method, *args, &block)
166
+ @client.send(:expire, args[0], @options[:expire_in].to_i) if @options[:expire_in] && args[0]
167
+ extract(method, result)
15
168
  else
16
169
  raise NameError, :message=> "method #{method} is not defined"
17
170
  end
@@ -25,13 +178,85 @@ module RedisWrapper
25
178
  end
26
179
  end
27
180
  end
28
-
29
- def get_key(*args)
30
- args.first.kind_of?(String) ? [args.shift, args] : [nil, args]
181
+
182
+ def handle(method, *args)
183
+ format = COMMANDS[method.to_sym][:namespace]
184
+ return args if format.nil?
185
+ case format[0]
186
+ when :first
187
+ if args[0]
188
+ first = args.shift
189
+ first = namespace(first) if first
190
+ args = args.map{|arg| prepare(arg)}
191
+ args.unshift(first)
192
+ end
193
+ args
194
+ when :all
195
+ namespace(args)
196
+ when :exclude_first
197
+ first = args.shift
198
+ args = namespace(args)
199
+ args.unshift(first) if first
200
+ when :exclude_last
201
+ last = args.last.kind_of?(Hash) ? args.pop : nil
202
+ args = namespace(args)
203
+ args.push(last) if !last.nil?
204
+ when :alternate
205
+ args.each_with_index do |arg,i|
206
+ case i.even?
207
+ when true
208
+ arg[i] = namespace(arg[i])
209
+ when false
210
+ arg[i] = prepare(arg[i])
211
+ end
212
+ end
213
+ when :sort
214
+ #TODO solve this problem
215
+ end
216
+ args
31
217
  end
32
-
33
- def handle(*args)
34
- args.map{|u| Entry.new(u).prepared_result} if args
218
+
219
+ def prepare(value)
220
+ Entry.new(value, @options).prepared_result if value
221
+ end
222
+
223
+ def namespace(args)
224
+ return args unless args && @namespace
225
+ case args
226
+ when Array
227
+ args.map {|k| namespace(k)}
228
+ when Hash
229
+ Hash[*args.map {|k, v| [namespace(k), prepare(v) ]}.flatten]
230
+ else
231
+ "#{@namespace}:#{args}"
232
+ end
233
+ end
234
+
235
+ def rm_namespace(args)
236
+ return args unless args && @namespace
237
+ case args.class
238
+ when Array
239
+ args.map {|k| rem_namespace(k)}
240
+ when Hash
241
+ Hash[*args.map {|k, v| [ rem_namespace(k), prepare(v) ]}.flatten]
242
+ else
243
+ args.to_s.gsub /^#{@namespace}:/, ""
244
+ end
245
+ end
246
+
247
+ def extract(method, args)
248
+ format = COMMANDS[method.to_sym]
249
+ return args if format.nil?
250
+ case format[1]
251
+ when :all
252
+ rm_namespace(args)
253
+ when nil
254
+ if args.class == String
255
+ Entry.new(args, @options).extracted_result
256
+ else
257
+ args.map{|arg| Entry.new(arg, @options).extracted_result}
258
+ end
259
+ end
35
260
  end
36
261
  end
37
262
  end
@@ -1,6 +1,6 @@
1
1
  module RedisWrapper
2
2
  MAJOR = 0
3
- MINOR = 1
3
+ MINOR = 2
4
4
  PATCH = 0
5
5
  VERSION = [MAJOR, MINOR, PATCH].compact.join('.')
6
6
  end
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.test_files = `git ls-files -- {spec,spec,features}/*`.split("\n")
17
17
  s.require_paths = ["lib"]
18
18
 
19
- s.homepage = "http://github.com/wakemaster39/redis-wrapper"
19
+ s.homepage = "http://github.com/wakemaster39/redis_wrapper"
20
20
  s.licenses = ["MIT"]
21
21
  s.rubygems_version = "1.8.10"
22
22
  s.summary = "High level wrapper around redis API"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-01-17 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &24307320 !ruby/object:Gem::Requirement
16
+ requirement: &23933640 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.2.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *24307320
24
+ version_requirements: *23933640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &24306720 !ruby/object:Gem::Requirement
27
+ requirement: &23933160 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *24306720
35
+ version_requirements: *23933160
36
36
  description: A high level wrapper around the redis-rb gem and API. Designed to be
37
37
  a drop in replacement for Redis class while handling object marshaling and compression,
38
38
  setting key expiries, and namespacing your keys
@@ -53,7 +53,7 @@ files:
53
53
  - redis_wrapper.gemspec
54
54
  - spec/entry_spec.rb
55
55
  - spec/redis_wrapper_spec.rb
56
- homepage: http://github.com/wakemaster39/redis-wrapper
56
+ homepage: http://github.com/wakemaster39/redis_wrapper
57
57
  licenses:
58
58
  - MIT
59
59
  post_install_message: