redis_obj 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60078190708a0aa3872d0df60a6d389ab6949117
4
- data.tar.gz: c88fb3d786df0eb865cdaf30816eada0b4315c8f
3
+ metadata.gz: 813c912763a0a73b1930d20bfbc7a67e72723ca9
4
+ data.tar.gz: e3795e83b616cdb64daab0d5f8ee920ad7a8f027
5
5
  SHA512:
6
- metadata.gz: 8304198906cc62aa89c17de1ee495d87c01f0f70569b548105a49195f68feb6b67c0d5d95e84dafc6dca7b770b15a1914f2a52c5bcb2dfd8ee4361d36a50dcef
7
- data.tar.gz: 6d813e8d0144add088b84b744c0a6952c7d6ef717e2fe9e908190b3a48401c6663be400dc72af0449ab768b12c913975b535615b56d345ec1c3970e5518c1dc2
6
+ metadata.gz: 3b1ad422bc3469a8c1a2ec6220aa59ea39f58ec3f4115b71151bbf380bb99e6d4896bbf5aef324ec43a6798327d20f5f4cd16fa196695e6030df5f2fa2f098eb
7
+ data.tar.gz: ea491f767b9a5e669c2af5cff37177af7a4d0e9ceec5dca95c7dc9bd807be8804513c89d86f7a61967f6323753c7ff07531c6d169c13ed71800c1c464b300323
@@ -0,0 +1,7 @@
1
+ script: bundle exec rspec spec
2
+ language: ruby
3
+ rvm:
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - jruby-19mode
7
+ - rbx-19mode
data/README.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # RedisObj
2
2
 
3
- TODO: Write a gem description
3
+ [![Build Status](https://travis-ci.org/tal/redis_obj.png)](https://travis-ci.org/tal/redis_obj)
4
+
5
+ This gem allows you to treat redis stores like ruby objects.
6
+
7
+ RedisObj::Set.new('myset').include?('foo')
8
+
9
+ Will run the redis command
10
+
11
+ SISMEMBER myset foo
12
+
13
+ So a hash key would act like a ruby hash, a set a set, and a list an array.
4
14
 
5
15
  ## Installation
6
16
 
@@ -18,7 +28,64 @@ Or install it yourself as:
18
28
 
19
29
  ## Usage
20
30
 
21
- TODO: Write usage instructions here
31
+ All the RedisObj wrappers have common ruby functions implemented
32
+
33
+ RedisObj::Set.new('set1').to_a
34
+ # => SMEMBERS set1
35
+
36
+ RedisObj::Set.new('set1') & RedisObj::Set.new('set2')
37
+ #=> SINTER set1 set2
38
+
39
+ RedisObj::Set.new('set1') - RedisObj::Set.new('set2')
40
+ # => SDIFF set1 set2
41
+
42
+ You can also just call the methods staright out
43
+
44
+ RedisObj::Hash.new('hash1').mget('key','key2')
45
+ # => HMGET hash1 key key2
46
+
47
+ ### Relations
48
+
49
+ You can embed redis objects into an object very easily.
50
+
51
+ class Foo
52
+ attr_accessor :id, :bar
53
+ include RedisObj::Relation
54
+ redis_set :baz
55
+ end
56
+
57
+ This will add a class and instance method to the object.
58
+
59
+ foo = Foo.new
60
+ foo.id = 123
61
+ foo.baz # => RedisObj::Set.new('foo:123:baz')
62
+
63
+ Class method:
64
+
65
+ Foo.redis_baz(id: 321) # => RedisObj::Set.new('foo:321:baz')
66
+ Foo.redis_baz(OpenStruct.new(id: 'myid')) # => RedisObj::Set.new('foo:myid:baz')
67
+
68
+ You can override the namespace for all redis relations easily:
69
+
70
+ class Foo
71
+ attr_accessor :id, :bar
72
+ include RedisObj::Relation
73
+ store_redis_in { "foons:#{id}:#{bar}" }
74
+ redis_set :baz, key: 'b'
75
+ redis_hash :hashy, key: 'h'
76
+ end
77
+
78
+ will allow the relations:
79
+
80
+ foo = Foo.new
81
+ foo.id = 123
82
+ foo.bar = 'mybar'
83
+ foo.baz # => RedisObj::Set.new('foons:123:mybar:b')
84
+ foo.hashy # => RedisObj::Hash.new('foons:123:mybar:h')
85
+
86
+ ### Examples
87
+
88
+ For more information on how relations work or how to use the gem check out the [examples](https://github.com/tal/redis_obj/wiki#examples).
22
89
 
23
90
  ## Contributing
24
91
 
data/TODO.md ADDED
@@ -0,0 +1,5 @@
1
+ * Detect if the redis client is currently pipelined, an instance of `Redis::Pipeline` and warn or error in that situation.
2
+ * Add range support to `List#[]`
3
+ * Optionally cache values when you pull down entire set
4
+ * In storage methods generate a random destination key if not given
5
+ * Allow sets and lists to interact with arrays directly for comparison actions
@@ -1,9 +1,12 @@
1
1
  require 'ostruct'
2
+ require 'forwardable'
3
+ require 'securerandom'
2
4
 
3
5
  %w{
4
6
  version
5
7
  base
6
8
  set
9
+ list
7
10
  sorted_set
8
11
  hash
9
12
  relations
@@ -1,4 +1,5 @@
1
1
  class RedisObj::Base
2
+ extend Forwardable
2
3
  attr_accessor :key, :redis
3
4
  def initialize redis, key=nil
4
5
  unless key
@@ -17,9 +18,12 @@ class RedisObj::Base
17
18
  redis.del(key)
18
19
  end
19
20
 
20
- private
21
+ def clear
22
+ redis.del(key)
23
+ end
21
24
 
22
25
  def get_keys(keys)
26
+ keys = keys.flatten
23
27
  if keys.first.respond_to?(:key)
24
28
  keys.collect(&:key)
25
29
  else
@@ -1,7 +1,10 @@
1
1
  class RedisObj::Hash < RedisObj::Base
2
- def del field
2
+ include Enumerable
3
+
4
+ def hdel field
3
5
  redis.hdel(key,field)
4
6
  end
7
+ alias delete hdel
5
8
 
6
9
  def incby field, amt
7
10
  if amt.is_a?(Float)
@@ -10,60 +13,119 @@ class RedisObj::Hash < RedisObj::Base
10
13
  redis.hincrby(key,field,amt)
11
14
  end
12
15
  end
13
- alias incbyfloat incby
16
+ alias hincrby incby
17
+ alias hincrbyfloat incby
18
+ alias hincbyfloat incby
14
19
 
20
+ # Increment by one
15
21
  def inc field
16
22
  incby(field,1)
17
23
  end
24
+ alias incr inc
18
25
 
26
+ # Decriment by one
19
27
  def dec field
20
28
  incby(field,-1)
21
29
  end
30
+ alias decr dec
22
31
 
23
- def mget *fields
32
+ def hmget *fields
24
33
  redis.hmget(key,*fields)
25
34
  end
35
+ alias values_at hmget
26
36
 
27
- def mset *fields
37
+ def hmset *fields
28
38
  redis.hmset(key,*fields)
29
39
  end
30
40
 
31
- def vals
41
+ def hvals
32
42
  redis.hvals(key)
33
43
  end
34
- alias values vals
44
+ alias values hvals
35
45
 
36
- def keys
46
+ def hkeys
37
47
  redis.hkeys(key)
38
48
  end
39
49
 
40
- def exists field
50
+ def hexists field
41
51
  redis.hexists(key,field)
42
52
  end
53
+ alias key? hexists
54
+ alias has_key? hexists
43
55
 
44
- def get field
56
+ def hget field
45
57
  redis.hget(key,field)
46
58
  end
47
- alias [] get
59
+ alias [] hget
48
60
 
49
- def set field, val
61
+ def hset field, val
50
62
  redis.hset(key,field,val)
51
63
  end
52
- alias []= set
64
+ alias []= hset
53
65
 
54
- def getall
66
+ def hgetall
55
67
  redis.hgetall(key)
56
68
  end
57
- alias to_h getall
69
+ alias to_h hgetall
70
+
71
+ def to_a
72
+ to_h.to_a
73
+ end
74
+
75
+ def each &blk
76
+ to_a.each(&blk)
77
+ end
58
78
 
59
- def len
79
+ def hlen
60
80
  redis.hlen(key)
61
81
  end
62
- alias size len
63
- alias count len
64
- alias length len
82
+ alias size hlen
83
+ alias count hlen
84
+ alias length hlen
85
+
86
+ def clear
87
+ redis.del(key) and self
88
+ end
89
+
90
+ def empty?
91
+ hlen == 0
92
+ end
93
+
94
+ def has_key? key
95
+ keys.include?(key)
96
+ end
97
+ alias include? has_key?
98
+ alias member? has_key?
99
+
100
+ def has_value? val
101
+ values.include?(val)
102
+ end
103
+
104
+ def merge! hsh
105
+ redis.hmset(key,hsh.to_a.flatten)
106
+ self
107
+ end
108
+
109
+ # Allow for non prefixed versions of the commands to be sent
110
+ # as well as making future proof for new versions of redis
111
+ def method_missing method, *arguments, &blk
112
+ if redis.respond_to?(method)
113
+ # If its a method available to redis just pass it along with the key
114
+ # as the first argument
115
+ redis.__send__(method,key,*arguments,&blk)
116
+ else
117
+ # If redis responds to the method prefixed with an h pass it along
118
+ if method.to_s[0] != 'h' && (new_method = "h#{method}") && redis.respond_to?(new_method)
119
+ self.send(new_method,*arguments,&blk)
120
+ else
121
+ super
122
+ end
123
+ end
124
+ end
65
125
 
66
- def setnx field, val
67
- redis.hsetnx(key,field,val)
126
+ def respond_to_missing?(method, include_private = false)
127
+ return true if redis.respond_to?(method)
128
+ method = method.to_s
129
+ method[0] != 'h' && redis.respond_to?("h#{method}") or super
68
130
  end
69
131
  end
@@ -1,58 +1,39 @@
1
1
  class RedisObj::List < RedisObj::Base
2
2
  include Enumerable
3
3
 
4
- def blpop *args
5
- redis.blpop(key,*args)
4
+ def first num=1
5
+ lrange(0,num-1)
6
6
  end
7
7
 
8
- def brpop *args
9
- redis.brpop(key,*args)
8
+ def take n
9
+ first(n)
10
10
  end
11
11
 
12
- def brpoplpush(destination, options = {})
13
- redis.brpoplpush(key,destination,options)
14
- end
15
-
16
- def lindex(index)
17
- redis.lindex(key,index)
18
- end
19
- alias [] lindex
20
-
21
- def linsert(where, pivot, value)
22
- redis.linsert(key,where,pivot,value)
23
- end
24
-
25
- def lrange(start, stop)
26
- redis.lrange(key, start, stop)
12
+ def last num=1
13
+ lrange(-1*num,-1)
27
14
  end
28
15
 
29
16
  def to_a
30
17
  lrange(0,-1)
31
18
  end
32
19
 
33
- def each &blk
34
- to_a.each(&blk)
35
- end
36
-
37
- def lrem(count, value)
38
- redis.lrem(key, count, value)
20
+ def lindex(index)
21
+ redis.lindex(key,index)
39
22
  end
23
+ alias [] lindex
24
+ alias at lindex
40
25
 
41
26
  def lset(index, value)
42
27
  redis.lset(key, index, value)
43
28
  end
44
29
  alias []= lset
45
30
 
46
- def ltrim(start, stop)
47
- redis.ltrim(key, start, stop)
48
- end
49
-
50
- def len
31
+ def llen
51
32
  redis.llen(key)
52
33
  end
53
- alias length len
54
- alias size len
55
- alias count len
34
+ alias length llen
35
+ alias size llen
36
+ alias count llen
56
37
 
57
38
  def lpop
58
39
  redis.lpop(key)
@@ -60,30 +41,65 @@ class RedisObj::List < RedisObj::Base
60
41
  alias shift lpop
61
42
 
62
43
  def lpush val
63
- redis.lpush(val)
44
+ redis.lpush(key,val)
64
45
  end
65
46
  alias unshift lpush
66
47
 
67
- def lpushx val
68
- redis.lpushx(key,val)
69
- end
70
-
71
48
  def rpop
72
49
  redis.rpop(key)
73
50
  end
74
51
  alias pop rpop
75
52
 
76
- def rpoplpush destination
77
- redis.rpoplpush(key, destination)
78
- end
79
-
80
53
  def rpush val
81
54
  redis.rpush(key,val)
82
55
  end
83
56
  alias << rpush
84
57
  alias push rpush
85
58
 
86
- def rpushx val
87
- redis.rpushx(key,val)
59
+ def include?(val)
60
+ warn('Calling include on redis list, must pull down entire list to process')
61
+ !!find {|v| v == val}
62
+ end
63
+
64
+ def drop n
65
+ redis.ltrim(key,n,-1)
66
+ self
67
+ end
68
+
69
+ def sample n=1
70
+ cnt = llen
71
+ if n==1
72
+ lindex(rand(cnt))
73
+ else
74
+ arr = []
75
+ n.times do
76
+ arr << lindex(rand(cnt))
77
+ end
78
+ arr
79
+ end
80
+ end
81
+
82
+ # Make future proof for new versions of redis
83
+ def method_missing method, *arguments, &blk
84
+ if redis.respond_to?(method)
85
+ # If its a method available to redis just pass it along with the key
86
+ # as the first argument
87
+ redis.__send__(method,key,*arguments,&blk)
88
+ else
89
+ super
90
+ end
91
+ end
92
+
93
+ def respond_to_missing?(method, include_private = false)
94
+ redis.respond_to?(method) || super
95
+ end
96
+
97
+ def_delegators :_delegated_to_a, :pack, :join, :each, :uniq
98
+
99
+ private
100
+
101
+ def _delegated_to_a
102
+ warn('Calling include on redis list, must pull down entire list to process')
103
+ to_a
88
104
  end
89
105
  end
@@ -1,74 +1,48 @@
1
1
  class RedisObj::Set < RedisObj::Base
2
2
  include Enumerable
3
3
 
4
- def members
4
+ def smembers
5
5
  redis.smembers(key)
6
6
  end
7
- alias to_a members
7
+ alias to_a smembers
8
8
 
9
- def ismember val
9
+ def each &blk
10
+ to_a.each(&blk)
11
+ end
12
+
13
+ def sismember val
10
14
  redis.sismember(key,val)
11
15
  end
12
- alias include? ismember
16
+ alias include? sismember
13
17
 
14
- def inter *keys
18
+ def sinter *keys
15
19
  redis.sinter(key,*get_keys(keys))
16
20
  end
17
- alias & inter
18
-
19
- def interstore destination, *keys
20
- redis.sinterstore(destination,key,*get_keys(keys))
21
- new_key = self.class.new(redis,destination)
22
-
23
- if block_given?
24
- begin
25
- yield(new_key)
26
- ensure
27
- redis.del(destination)
28
- end
29
- end
21
+ alias & sinter
22
+ alias intersection sinter
30
23
 
31
- new_key
24
+ def sinterstore destination, *keys, &blk
25
+ store_block_syntax(:sinterstore,destination,keys,&blk)
32
26
  end
33
27
 
34
- def diff *keys
28
+ def sdiff *keys
35
29
  redis.sdiff(key,*get_keys(keys))
36
30
  end
37
- alias - diff
38
-
39
- def diffstore destination, *keys
40
- redis.sdiffstore(destination,key,*get_keys(keys))
41
- new_key = self.class.new(redis,destination)
31
+ alias - sdiff
32
+ alias difference sdiff
42
33
 
43
- if block_given?
44
- begin
45
- yield(new_key)
46
- ensure
47
- redis.del(destination)
48
- end
49
- end
50
-
51
- new_key
34
+ def sdiffstore destination, *keys, &blk
35
+ store_block_syntax(:sdiffstore,destination,keys,&blk)
52
36
  end
53
37
 
54
- def union *keys
38
+ def sunion *keys
55
39
  redis.sunion(key,*get_keys(keys))
56
40
  end
57
- alias | union
58
-
59
- def unionstore destination, *keys
60
- redis.sunionstore(destination,key,*get_keys(keys))
61
- new_key = self.class.new(redis,destination)
62
-
63
- if block_given?
64
- begin
65
- yield(new_key)
66
- ensure
67
- redis.del(destination)
68
- end
69
- end
41
+ alias | sunion
42
+ alias + sunion
70
43
 
71
- new_key
44
+ def sunionstore destination, *keys, &blk
45
+ store_block_syntax(:sunionstore,destination,keys,&blk)
72
46
  end
73
47
 
74
48
  def pop
@@ -77,25 +51,91 @@ class RedisObj::Set < RedisObj::Base
77
51
 
78
52
  def add val
79
53
  redis.sadd(key,val)
54
+ self
80
55
  end
81
56
  alias << add
82
57
 
83
- def rem val
84
- redis.srem(key,val)
58
+ def add? val
59
+ redis.sadd(key,val) ? self : nil
60
+ end
61
+
62
+ def remove(val)
63
+ srem(val)
64
+ self
65
+ end
66
+
67
+ def remove?(val)
68
+ srem(val) ? self : nil
85
69
  end
86
70
 
87
71
  def srandmember num=1
88
72
  redis.srandmember(key,num)
89
73
  end
74
+ alias sample srandmember
90
75
 
91
- def card
76
+ def scard
92
77
  redis.scard(key)
93
78
  end
94
- alias length card
95
- alias size card
96
- alias count card
79
+ alias length scard
80
+ alias size scard
81
+ alias count scard
97
82
 
98
- def each &blk
99
- to_a.each(&blk)
83
+ def empty?
84
+ scard == 0
85
+ end
86
+
87
+ def delete_if(&blk)
88
+ vals_to_delete = select(&blk)
89
+ redis.srem(key,vals_to_delete)
90
+ vals_to_delete
91
+ end
92
+
93
+ # Allow for non prefixed versions of the commands to be sent
94
+ # as well as making future proof for new versions of redis
95
+ def method_missing method, *arguments, &blk
96
+ if redis.respond_to?(method)
97
+ # If its a method available to redis just pass it along with the key
98
+ # as the first argument
99
+ redis.__send__(method,key,*arguments,&blk)
100
+ else
101
+ # If redis responds to the method prefixed with an h pass it along
102
+ if method.to_s[0] != 's' && (new_method = "s#{method}") && redis.respond_to?(new_method)
103
+ self.send(new_method,*arguments,&blk)
104
+ else
105
+ super
106
+ end
107
+ end
108
+ end
109
+
110
+ def respond_to_missing?(method, include_private = false)
111
+ return true if redis.respond_to?(method)
112
+ method = method.to_s
113
+ method[0] != 's' && redis.respond_to?("s#{method}") or super
114
+ end
115
+
116
+ private
117
+
118
+ # If a block is passed yeild up the new key object and
119
+ # then delete the key afterwards
120
+ def store_block_syntax(command, destination, keys, &blk)
121
+ if block_given?
122
+ keys.unshift destination
123
+ destination = SecureRandom.uuid
124
+ end
125
+
126
+ keys.unshift(key)
127
+ redis.__send__(command,destination,*get_keys(keys))
128
+
129
+ new_key = self.class.new(redis,destination)
130
+
131
+ if block_given?
132
+ begin
133
+ yield(new_key)
134
+ ensure
135
+ redis.del(destination)
136
+ end
137
+ else
138
+ new_key
139
+ end
100
140
  end
101
141
  end
@@ -1,14 +1,11 @@
1
1
  class RedisObj::SortedSet < RedisObj::Base
2
- def add score, member
3
- redis.zadd(key,score,member)
4
- end
5
-
6
- def rem member
7
- redis.zrem(key,mem)
8
- end
9
-
10
- def card min=0,max=0
2
+ def card min=nil,max=nil
11
3
  if min
4
+ if min.respond_to?(:max) && min.respond_to?(:min)
5
+ max = min.max
6
+ min = min.min
7
+ end
8
+
12
9
  redis.zcount(key,min,max)
13
10
  else
14
11
  redis.zcard(key)
@@ -16,74 +13,84 @@ class RedisObj::SortedSet < RedisObj::Base
16
13
  end
17
14
  alias length card
18
15
  alias size card
19
- alias count card
16
+ alias zcount card
20
17
 
21
- def incby amt, member
18
+ def zincrby amt, member
22
19
  redis.zincby(key,amt,member)
23
20
  end
21
+ alias incby zincrby
24
22
 
25
23
  def inc member
26
- incby(1,member)
24
+ incrby(1,member)
27
25
  end
26
+ alias incr inc
28
27
 
29
28
  def dec member
30
- incby(-1,member)
29
+ incrby(-1,member)
31
30
  end
31
+ alias decr dec
32
32
 
33
- def range start, stop, opts={}
34
- redis.zrange(key,start,stop,opts)
35
- end
33
+ def zremrangebyrank start, stop=nil
34
+ if start.respond_to?(:max) && start.respond_to?(:min)
35
+ stop = start.max
36
+ start = start.min
37
+ end
36
38
 
37
- def revrange start, stop, opts={}
38
- redis.zrevrange(key,start,stop,opts)
39
+ redis.zremrangebyrank(key,start,stop)
39
40
  end
40
41
 
41
- def rangebyscore start, stop, opts={}
42
- redis.zrangebyscore(key,start,stop,opts)
43
- end
42
+ def zremrangebyscore start, stop=nil
43
+ if start.respond_to?(:max) && start.respond_to?(:min)
44
+ stop = start.max
45
+ start = start.min
46
+ end
44
47
 
45
- def revrangebyscore start, stop, opts={}
46
- redis.zrevrangebyscore(key,start,stop,opts)
48
+ redis.zremrangebyscore(key,start,stop)
47
49
  end
48
50
 
49
- def rank mem
50
- redis.rank(key,mem)
51
+ def zinterstore(destination, keys, options = {}, &blk)
52
+ store_block_syntax(:zinterstore,destination,keys,options,&blk)
51
53
  end
52
54
 
53
- def revrank mem
54
- redis.revrank(key,mem)
55
+ def zunionstore(destination, keys, options = {}, &blk)
56
+ store_block_syntax(:zunionstore,destination,keys,options,&blk)
55
57
  end
56
58
 
57
- def remrangebyrank start, stop
58
- redis.zremrangebyrank(key,start,stop)
59
+ # Allow for non prefixed versions of the commands to be sent
60
+ # as well as making future proof for new versions of redis
61
+ def method_missing method, *arguments, &blk
62
+ if redis.respond_to?(method)
63
+ # If its a method available to redis just pass it along with the key
64
+ # as the first argument
65
+ redis.__send__(method,key,*arguments,&blk)
66
+ else
67
+ # If redis responds to the method prefixed with an h pass it along
68
+ if method.to_s[0] != 'z' && (new_method = "z#{method}") && redis.respond_to?(new_method)
69
+ self.send(new_method,*arguments,&blk)
70
+ else
71
+ super
72
+ end
73
+ end
59
74
  end
60
75
 
61
- def remrangebyscore start, stop
62
- redis.zremrangebyscore(key,start,stop)
76
+ def respond_to_missing?(method, include_private = false)
77
+ return true if redis.respond_to?(method)
78
+ method = method.to_s
79
+ method[0] != 'z' && redis.respond_to?("z#{method}") or super
63
80
  end
64
81
 
65
- def interstore(destination, keys, options = {})
66
- keys = [key]+keys
67
-
68
- redis.zinterstore(destination,keys,options)
69
-
70
- new_key = self.class.new(redis,destination)
82
+ private
71
83
 
84
+ # If a block is passed yeild up the new key object and
85
+ # then delete the key afterwards
86
+ def store_block_syntax(command, destination, keys, options,&blk)
72
87
  if block_given?
73
- begin
74
- yield(new_key)
75
- ensure
76
- redis.del(destination)
77
- end
88
+ keys.unshift destination
89
+ destination = SecureRandom.uuid
78
90
  end
79
91
 
80
- new_key
81
- end
82
-
83
- def unionstore(destination, keys, options = {})
84
- keys = [key]+keys
85
-
86
- redis.zunionstore(destination,keys,options)
92
+ keys.unshift(key)
93
+ redis.__send__(command,destination,get_keys(keys),options)
87
94
 
88
95
  new_key = self.class.new(redis,destination)
89
96
 
@@ -93,9 +100,8 @@ class RedisObj::SortedSet < RedisObj::Base
93
100
  ensure
94
101
  redis.del(destination)
95
102
  end
103
+ else
104
+ new_key
96
105
  end
97
-
98
- new_key
99
106
  end
100
-
101
107
  end
@@ -1,3 +1,3 @@
1
1
  module RedisObj
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -22,5 +22,5 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
24
  spec.add_development_dependency "rake"
25
- spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "rspec", '~> 2.14.0.rc1'
26
26
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe RedisObj::Hash do
4
+ let(:redis_method) {:"some_redis_method!"}
5
+ let(:redis) { double(Redis, redis_method => true) }
6
+ let(:key) { "key#{rand}" }
7
+ let(:val) { rand }
8
+ subject {RedisObj::Hash.new(redis,key)}
9
+
10
+ it_should_behave_like "a method missing object", 'h'
11
+
12
+ describe '#hget' do
13
+ let(:index) { rand(10000) }
14
+ before do
15
+ expect(redis).to receive(:hget).with(key,index).once
16
+ end
17
+
18
+ it { subject.hget(index) }
19
+ it { subject.get(index) }
20
+ it { subject[index] }
21
+ end
22
+
23
+ describe '#hset' do
24
+ let(:index) { rand(10000) }
25
+ let(:val) { rand }
26
+ before do
27
+ expect(redis).to receive(:hset).with(key,index,val).once
28
+ end
29
+
30
+ it { subject.hset(index,val) }
31
+ it { subject.set(index,val) }
32
+ it { subject[index] = val}
33
+ end
34
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe RedisObj::List do
4
+ let(:redis_method) {:"some_redis_method!"}
5
+ let(:redis) { double(Redis, redis_method => true) }
6
+ let(:key) { "key#{rand}" }
7
+ let(:val) { rand }
8
+ subject {RedisObj::List.new(redis,key)}
9
+
10
+ it_should_behave_like "a method missing object"
11
+
12
+ describe '#lindex' do
13
+ let(:val) { rand }
14
+ before do
15
+ expect(redis).to receive(:lindex).with(key,val).once
16
+ end
17
+
18
+ it { subject.lindex(val) }
19
+ it { subject[val] }
20
+ it { subject.at(val) }
21
+ end
22
+
23
+ describe '#first' do
24
+ it "should work with no args" do
25
+ expect(redis).to receive(:lrange).with(key,0,0).once
26
+ subject.first
27
+ end
28
+
29
+ it "should work with no args" do
30
+ expect(redis).to receive(:lrange).with(key,0,2).once
31
+ subject.first(3)
32
+ end
33
+
34
+ it "should work with no args" do
35
+ expect(redis).to receive(:lrange).with(key,0,2).once
36
+ subject.take(3)
37
+ end
38
+ end
39
+
40
+ describe '#last' do
41
+ it "should work with no args" do
42
+ expect(redis).to receive(:lrange).with(key,-1,-1).once
43
+ subject.last
44
+ end
45
+
46
+ it "should work with no args" do
47
+ expect(redis).to receive(:lrange).with(key,-3,-1).once
48
+ subject.last(3)
49
+ end
50
+ end
51
+
52
+ describe '#set' do
53
+ let(:index) { rand(100000) }
54
+ before do
55
+ expect(redis).to receive(:lset).with(key,index,val).once
56
+ end
57
+
58
+ it { subject.lset(index,val) }
59
+ it { subject[index] = val }
60
+ end
61
+
62
+ describe '#llen' do
63
+ before do
64
+ expect(redis).to receive(:llen).with(key).once
65
+ end
66
+
67
+ it { subject.length }
68
+ it { subject.size }
69
+ it { subject.count }
70
+ it { subject.llen }
71
+ end
72
+
73
+ describe '#lpop' do
74
+ before do
75
+ expect(redis).to receive(:lpop).with(key).once
76
+ end
77
+
78
+ it { subject.lpop }
79
+ it { subject.shift }
80
+ end
81
+
82
+ describe '#lpush' do
83
+ before do
84
+ expect(redis).to receive(:lpush).with(key,val).once
85
+ end
86
+
87
+ it { subject.lpush val }
88
+ it { subject.unshift val }
89
+ end
90
+
91
+ describe '#rpop' do
92
+ before do
93
+ expect(redis).to receive(:rpop).with(key).once
94
+ end
95
+
96
+ it { subject.rpop }
97
+ it { subject.pop }
98
+ end
99
+
100
+ describe '#rpush' do
101
+ before do
102
+ expect(redis).to receive(:rpush).with(key,val).once
103
+ end
104
+
105
+ it { subject.rpush val }
106
+ it { subject << val}
107
+ it { subject.push val}
108
+ end
109
+
110
+ end
@@ -0,0 +1,206 @@
1
+ require 'spec_helper'
2
+
3
+ describe RedisObj::Set do
4
+ let(:redis_method) {:"some_redis_method!"}
5
+ let(:redis) { double(Redis, redis_method => true) }
6
+ let(:key) { "key#{rand}" }
7
+ let(:val) { rand }
8
+ subject {RedisObj::Set.new(redis,key)}
9
+
10
+ describe '#smembers' do
11
+ before do
12
+ expect(redis).to receive(:smembers).with(key).once
13
+ end
14
+
15
+ it { subject.smembers }
16
+ it { subject.to_a }
17
+ it { subject.members }
18
+ end
19
+
20
+ describe '#sismember' do
21
+ before do
22
+ expect(redis).to receive(:sismember).with(key,val).once
23
+ end
24
+
25
+ it { subject.sismember val }
26
+ it { subject.include? val }
27
+ it { subject.ismember val }
28
+ end
29
+
30
+ describe 'other key interaction' do
31
+ let(:keys) { %w{key1 key2 key3} }
32
+ let(:objs) { %w{key1 key2 key3}.collect {|k| RedisObj::Set.new(redis,k)} }
33
+ let(:destination) { 'destination' }
34
+
35
+ let(:test_key) {keys.first}
36
+ let(:test_objs) {objs.first}
37
+
38
+ describe '#sinter' do
39
+ before do
40
+ expect(redis).to receive(:sinter).with(key,*keys).once
41
+ end
42
+
43
+ it { subject.sinter *keys }
44
+ it { subject.sinter keys }
45
+ it { subject.inter keys }
46
+ it { subject & keys }
47
+ it { subject.intersection keys }
48
+
49
+ it { subject.sinter *objs }
50
+ it { subject.sinter objs }
51
+ it { subject.inter objs }
52
+ it { subject & objs }
53
+ it { subject.intersection objs }
54
+ end
55
+
56
+ describe '#sdiff' do
57
+ before do
58
+ expect(redis).to receive(:sdiff).with(key,*keys).once
59
+ end
60
+
61
+ it { subject.sdiff *keys }
62
+ it { subject.sdiff keys }
63
+ it { subject.diff keys }
64
+ it { subject - keys }
65
+ it { subject.difference keys }
66
+
67
+ it { subject.sdiff *objs }
68
+ it { subject.sdiff objs }
69
+ it { subject.diff objs }
70
+ it { subject - objs }
71
+ it { subject.difference objs }
72
+ end
73
+
74
+ describe '#sunion' do
75
+ before do
76
+ expect(redis).to receive(:sunion).with(key,*keys).once
77
+ end
78
+
79
+ it { subject.sunion *keys }
80
+ it { subject.sunion keys }
81
+ it { subject.union keys }
82
+ it { subject | keys }
83
+ it { subject + keys }
84
+
85
+ it { subject.sunion *objs }
86
+ it { subject.sunion objs }
87
+ it { subject.union objs }
88
+ it { subject | objs }
89
+ it { subject + objs }
90
+ end
91
+
92
+ describe '#sinterstore' do
93
+ before do
94
+ expect(redis).to receive(:sinterstore).with(destination,key,*keys).once
95
+ end
96
+
97
+ it { subject.sinterstore destination, *keys }
98
+ it { subject.interstore destination, keys }
99
+
100
+ it 'should delete key after when returning block' do
101
+ expect(redis).to receive(:del).with(destination).once
102
+ expect(redis).to receive(redis_method).with(destination).once
103
+ expect(SecureRandom).to receive(:uuid).once.and_return(destination)
104
+
105
+ subject.sinterstore *keys do |new_key|
106
+ new_key.send redis_method
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ describe '#sdiffstore' do
113
+ before do
114
+ expect(redis).to receive(:sdiffstore).with(destination,key,*keys).once
115
+ end
116
+
117
+ it { subject.sdiffstore destination, *keys }
118
+ it { subject.diffstore destination, keys }
119
+
120
+ it 'should delete key after when returning block' do
121
+ expect(redis).to receive(:del).with(destination).once
122
+ expect(redis).to receive(redis_method).with(destination).once
123
+ expect(SecureRandom).to receive(:uuid).once.and_return(destination)
124
+
125
+ subject.sdiffstore *keys do |new_key|
126
+ new_key.send redis_method
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+ describe '#sunionstore' do
133
+ before do
134
+ expect(redis).to receive(:sunionstore).with(destination,key,*keys).once
135
+ end
136
+
137
+ it { subject.sunionstore destination, *keys }
138
+ it { subject.unionstore destination, keys }
139
+
140
+ it 'should delete key after when returning block' do
141
+ expect(redis).to receive(:del).with(destination).once
142
+ expect(redis).to receive(redis_method).with(destination).once
143
+ expect(SecureRandom).to receive(:uuid).once.and_return(destination)
144
+
145
+ subject.sunionstore *keys do |new_key|
146
+ new_key.send redis_method
147
+ end
148
+ end
149
+
150
+ end
151
+
152
+ end
153
+
154
+ describe '#pop' do
155
+ before do
156
+ expect(redis).to receive(:pop).with(key).once
157
+ end
158
+
159
+ it { subject.pop }
160
+ end
161
+
162
+ describe '#srandmember' do
163
+ before do
164
+ expect(redis).to receive(:srandmember).with(key,1).once
165
+ end
166
+
167
+ it { subject.srandmember }
168
+ it { subject.randmember }
169
+ it { subject.sample }
170
+ end
171
+
172
+ describe '#scard' do
173
+ before do
174
+ expect(redis).to receive(:scard).with(key).once
175
+ end
176
+
177
+ it { subject.scard }
178
+ it { subject.card }
179
+ it { subject.length }
180
+ it { subject.size }
181
+ it { subject.count }
182
+ end
183
+
184
+ describe '#add' do
185
+ let(:ret) {double('return')}
186
+ before do
187
+ expect(redis).to receive(:sadd).with(key,val).once.and_return(ret)
188
+ end
189
+
190
+ it { subject.add(val).should be subject }
191
+ it { subject.sadd(val).should be ret }
192
+ it { (subject << val).should be subject }
193
+ end
194
+
195
+ describe '#remove' do
196
+ let(:ret) {double('return')}
197
+ before do
198
+ expect(redis).to receive(:srem).with(key,val).once.and_return(ret)
199
+ end
200
+
201
+ it { subject.srem(val).should be ret }
202
+ it { subject.remove(val).should be subject }
203
+ end
204
+
205
+ it_should_behave_like "a method missing object", 's'
206
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe RedisObj::SortedSet do
4
+ let(:redis_method) {:"some_redis_method!"}
5
+ let(:redis) { double(Redis, redis_method => true) }
6
+ let(:key) { "key#{rand}" }
7
+ let(:val) { rand }
8
+ subject {RedisObj::SortedSet.new(redis,key)}
9
+
10
+ it_should_behave_like "a method missing object", 'z'
11
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe RedisObj do
4
- let(:base_redis) { mock("BaseRedis") }
4
+ let(:base_redis) { double("BaseRedis") }
5
5
  before { RedisObj.redis = base_redis }
6
6
 
7
7
  let(:test_klass) do
@@ -37,7 +37,7 @@ describe RedisObj do
37
37
 
38
38
  describe "global redis instance" do
39
39
  subject{obj.friends}
40
- let(:redis) {mock('Redis')}
40
+ let(:redis) {double('Redis')}
41
41
 
42
42
  before { RedisObj.redis = redis; test_klass.redis_set :friends }
43
43
  after { RedisObj.redis = base_redis }
@@ -63,7 +63,7 @@ describe RedisObj do
63
63
  end
64
64
 
65
65
  describe 'redis_set defined default key' do
66
- let(:redis) {mock('Redis')}
66
+ let(:redis) {double('Redis')}
67
67
  before do
68
68
  test_klass.redis_set :friends
69
69
  test_klass.redis_set :friends2, key: 'f', redis: redis
@@ -16,7 +16,50 @@ RSpec.configure do |config|
16
16
  config.order = 'random'
17
17
  end
18
18
 
19
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..','lib')))
19
+ # $:.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..','lib')))
20
20
 
21
21
  require 'redis'
22
22
  require 'redis_obj'
23
+
24
+
25
+ shared_examples "a method missing object" do |has_pefix=false|
26
+ describe 'method missing' do
27
+ let(:non_redis_method) { :"rand_method_#{rand}" }
28
+
29
+ it 'should respond to redis methods' do
30
+ subject.respond_to?(redis_method).should be true
31
+ end
32
+
33
+ it 'should pass method along' do
34
+ expect(redis).to receive(redis_method).with(key)
35
+ subject.__send__(redis_method)
36
+ end
37
+
38
+ it 'should not respond to non redis methods' do
39
+ subject.respond_to?(non_redis_method).should be false
40
+ end
41
+
42
+ it 'should error if you call non redis method' do
43
+ redis.should_not_receive(:non_redis_method)
44
+ expect { subject.send(non_redis_method) }.to raise_error(NoMethodError)
45
+ end
46
+
47
+ if has_pefix
48
+ let(:prefixed_redis_method) { :"#{has_pefix}prefixed_redis_method" }
49
+ before do
50
+ allow(redis).to receive(prefixed_redis_method)
51
+ end
52
+
53
+ it { subject.respond_to?(prefixed_redis_method).should be true }
54
+ it 'should pass method along' do
55
+ expect(redis).to receive(prefixed_redis_method).with(key)
56
+ subject.__send__(prefixed_redis_method)
57
+ end
58
+ it { subject.respond_to?(:prefixed_redis_method).should be true }
59
+ it 'should pass method along' do
60
+ expect(redis).to receive(:prefixed_redis_method).with(key)
61
+ subject.__send__(:prefixed_redis_method)
62
+ end
63
+ end
64
+ end
65
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_obj
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tal Atlas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-06 00:00:00.000000000 Z
11
+ date: 2013-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 2.14.0.rc1
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 2.14.0.rc1
69
69
  description: methods for managing redis keys in an object oriented manner
70
70
  email:
71
71
  - me@tal.by
@@ -75,10 +75,12 @@ extra_rdoc_files: []
75
75
  files:
76
76
  - .gitignore
77
77
  - .rspec
78
+ - .travis.yml
78
79
  - Gemfile
79
80
  - LICENSE.txt
80
81
  - README.md
81
82
  - Rakefile
83
+ - TODO.md
82
84
  - lib/redis_obj.rb
83
85
  - lib/redis_obj/base.rb
84
86
  - lib/redis_obj/hash.rb
@@ -88,6 +90,10 @@ files:
88
90
  - lib/redis_obj/sorted_set.rb
89
91
  - lib/redis_obj/version.rb
90
92
  - redis_obj.gemspec
93
+ - spec/object_types/hash_spec.rb
94
+ - spec/object_types/list_spec.rb
95
+ - spec/object_types/set_spec.rb
96
+ - spec/object_types/sorted_set_spec.rb
91
97
  - spec/redis_obj_class_methods_spec.rb
92
98
  - spec/redis_obj_spec.rb
93
99
  - spec/spec_helper.rb
@@ -116,6 +122,10 @@ signing_key:
116
122
  specification_version: 4
117
123
  summary: kinda like a redis ORM
118
124
  test_files:
125
+ - spec/object_types/hash_spec.rb
126
+ - spec/object_types/list_spec.rb
127
+ - spec/object_types/set_spec.rb
128
+ - spec/object_types/sorted_set_spec.rb
119
129
  - spec/redis_obj_class_methods_spec.rb
120
130
  - spec/redis_obj_spec.rb
121
131
  - spec/spec_helper.rb