redis_obj 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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