redpear 0.6.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,147 @@
1
+ class Redpear::Store::Set < Redpear::Store::Enumerable
2
+ include Enumerable
3
+
4
+ # @yield over a field-value pair
5
+ # @yieldparam [String] field
6
+ # @yieldparam [String] value
7
+ def each(&block)
8
+ members.each(&block)
9
+ end
10
+
11
+ # @return [Set] all members
12
+ def all
13
+ members.to_set
14
+ end
15
+ alias_method :to_set, :all
16
+ alias_method :value, :all
17
+
18
+ # @return [Array] the array of members
19
+ def members
20
+ conn.smembers(key) || []
21
+ end
22
+ alias_method :to_a, :members
23
+
24
+ # @return [Integer] the number of items in the set
25
+ def length
26
+ conn.scard key
27
+ end
28
+ alias_method :size, :length
29
+
30
+ # Adds a single value. Chainable example:
31
+ # set << 'a' << 'b'
32
+ # @param [String] value
33
+ # A value to add
34
+ def add(value)
35
+ conn.sadd key, value
36
+ self
37
+ end
38
+ alias_method :<<, :add
39
+
40
+ # @param [String] value
41
+ # A value to delete
42
+ def delete(value)
43
+ conn.srem key, value
44
+ end
45
+ alias_method :remove, :delete
46
+
47
+ # @return [Boolean] true, if value is included
48
+ def include?(value)
49
+ !!conn.sismember(key, value)
50
+ end
51
+ alias_method :member?, :include?
52
+
53
+ # @return [Boolean] true, if empty
54
+ def empty?
55
+ length.zero?
56
+ end
57
+
58
+ # Removes a random value
59
+ # @return [String] the removed value
60
+ def pop
61
+ conn.spop key
62
+ end
63
+
64
+ # Subtracts values using other sets
65
+ # @param [multiple] others
66
+ # The other sets
67
+ # @return [Array] remaining values
68
+ def diff(*others)
69
+ conn.sdiff key, *others.map(&:to_s)
70
+ end
71
+ alias_method :-, :diff
72
+
73
+ # Store the result of a diff in a new +target+ key
74
+ # @param [String] target
75
+ # The target key
76
+ # @param [multiple] others
77
+ # The other sets
78
+ # @return [Redpear::Store::Set] the result set
79
+ def diffstore(target, *others)
80
+ conn.sdiffstore target.to_s, key, *others.map(&:to_s)
81
+ self.class.new target.to_s, conn
82
+ end
83
+
84
+ # Merges values of two sets
85
+ # @param [multiple] others
86
+ # The other sets
87
+ # @return [Array] union
88
+ def union(*others)
89
+ conn.sunion key, *others.map(&:to_s)
90
+ end
91
+ alias_method :+, :union
92
+ alias_method :|, :union
93
+ alias_method :merge, :union
94
+
95
+ # Store the result of a union in a new +target+ key
96
+ # @param [Redpear::Store::Set] other
97
+ # The other set
98
+ # @param [multiple] others
99
+ # The other sets
100
+ # @return [Redpear::Store::Set] the result set
101
+ def unionstore(target, *others)
102
+ conn.sunionstore target.to_s, key, *others.map(&:to_s)
103
+ self.class.new target.to_s, conn
104
+ end
105
+
106
+ # @param [multiple] other
107
+ # The other sets
108
+ # @return [Array] the intersection +other+ set
109
+ def inter(*others)
110
+ conn.sinter key, *others.map(&:to_s)
111
+ end
112
+ alias_method :intersect, :inter
113
+ alias_method :inter, :inter
114
+ alias_method :&, :inter
115
+
116
+ # Store the result of an intersection in a new +target+ key
117
+ # @param [String] target
118
+ # The target key
119
+ # @param [multiple] others
120
+ # The other sets
121
+ # @return [Redpear::Store::Set] the result set
122
+ def interstore(target, *others)
123
+ conn.sinterstore target.to_s, key, *others.map(&:to_s)
124
+ self.class.new target.to_s, conn
125
+ end
126
+
127
+ # @return [String] a random member
128
+ def random
129
+ conn.srandmember key
130
+ end
131
+
132
+ # Comparator
133
+ # @return [Boolean] true if contains same members as other
134
+ def ==(other)
135
+ other.respond_to?(:to_set) && other.to_set == to_set
136
+ end
137
+
138
+ # Move a value to +target+ set
139
+ # @param [String] target
140
+ # The key of the target set
141
+ # @param [String] value
142
+ # The value to move
143
+ def move(target, value)
144
+ conn.smove key, target.to_s, value
145
+ end
146
+
147
+ end
@@ -0,0 +1,239 @@
1
+ class Redpear::Store::SortedSet < Redpear::Store::Enumerable
2
+ include Enumerable
3
+
4
+ # @yield over a field-score pair
5
+ # @yieldparam [String] field
6
+ # @yieldparam [String] score
7
+ def each(&block)
8
+ all.each(&block)
9
+ end
10
+
11
+ # @param [Hash] options
12
+ # @option [Boolean] with_scores
13
+ # Return with scores, defaults to true
14
+ # @return [Array] all elements
15
+ def all(options = {})
16
+ slice(0..-1, options)
17
+ end
18
+ alias_method :to_a, :all
19
+
20
+ # @return [Integer] the number of items in the set
21
+ def length
22
+ conn.zcard key
23
+ end
24
+ alias_method :size, :length
25
+
26
+ # @param [Range] range
27
+ # @return [Integer] the number of items within given score `range`
28
+ def count(range)
29
+ conn.zcount key, *range_pair(range)
30
+ end
31
+
32
+ # Adds a single member.
33
+ # @param [String] member
34
+ # A member to add
35
+ # @param [Integer] score
36
+ # The score
37
+ def add(member, score)
38
+ conn.zadd key, score, member
39
+ self
40
+ end
41
+ alias_method :[]=, :add
42
+
43
+ # Determines the score of a member
44
+ # @param [String] member
45
+ # @return [Integer] the score for the given `member`
46
+ def score(member)
47
+ number = conn.zscore(key, member)
48
+ number.to_f if number
49
+ end
50
+ alias_method :[], :score
51
+
52
+ # Determines the index of a member (based on ascending scores)
53
+ # @param [String] member
54
+ # @return [Integer] the index for the given `member`
55
+ def index(member)
56
+ number = conn.zrank(key, member)
57
+ number.to_i if number
58
+ end
59
+ alias_method :rank, :index
60
+
61
+ # Determines the reverse index of a member (based on descending scores)
62
+ # @param [String] member
63
+ # @return [Integer] the index for the given `member`
64
+ def rindex(member)
65
+ number = conn.zrevrank(key, member)
66
+ number.to_i if number
67
+ end
68
+ alias_method :rrank, :rindex
69
+
70
+ # @param [String] member
71
+ # The `member` to delete
72
+ def delete(member)
73
+ conn.zrem key, member
74
+ end
75
+
76
+ # @return [Boolean] true, if member is included
77
+ def include?(member)
78
+ !!conn.zscore(key, member)
79
+ end
80
+ alias_method :member?, :include?
81
+
82
+ # @return [Boolean] true, if empty
83
+ def empty?
84
+ length.zero?
85
+ end
86
+
87
+ # Returns a slice of members between index +range+, with the lower index returned first
88
+ # @param [Range] range
89
+ # The index range of the elements
90
+ # @param [Hash] options
91
+ # @option [Boolean] with_scores
92
+ # Return with scores, defaults to true
93
+ # @return [Array] the members
94
+ def slice(range, options = {})
95
+ start, finish = range_pair(range)
96
+ fetch_range :zrange, start, finish, options
97
+ end
98
+ alias_method :top, :slice
99
+
100
+ # Returns a slice of members between rindex +range+, with the higher index returned first
101
+ # @param [Range] range
102
+ # The rindex range of the elements
103
+ # @param [Hash] options
104
+ # @option [Boolean] with_scores
105
+ # Return with scores, defaults to true
106
+ # @return [Array] the members
107
+ def rslice(range, options = {})
108
+ start, finish = range_pair(range)
109
+ fetch_range :zrevrange, start, finish, options
110
+ end
111
+ alias_method :bottom, :rslice
112
+
113
+ # Selects members between a score +range+. Lower scores returned first
114
+ # @param [Range] range
115
+ # The score range of the elements
116
+ # @param [Hash] options
117
+ # @option [Boolean] with_scores
118
+ # Return with scores, defaults to true
119
+ # @option [Integer] limit
120
+ # Limit the results
121
+ # @return [Array] the members
122
+ def select(range, options = {})
123
+ start, finish = range_pair(range)
124
+ fetch_range :zrangebyscore, start, finish, options
125
+ end
126
+
127
+ # Selects members between a score +range+. Higher scores returned first
128
+ # @param [Range] range
129
+ # The score range of the elements
130
+ # @param [Hash] options
131
+ # @option [Boolean] with_scores
132
+ # Return with scores, defaults to true
133
+ # @option [Integer] limit
134
+ # Limit the results
135
+ # @return [Array] the members
136
+ def rselect(range, options = {})
137
+ start, finish = range_pair(range)
138
+ fetch_range :zrevrangebyscore, finish, start, options
139
+ end
140
+
141
+ # Comparator
142
+ # @return [Boolean] true if contains same members as other
143
+ def ==(other)
144
+ other.respond_to?(:to_a) && other.to_a == to_a
145
+ end
146
+
147
+ # @param [Integer] index
148
+ # @param [Hash] options
149
+ # @option [Boolean] with_scores
150
+ # Return with scores, defaults to true
151
+ # @return [Array] member + score for given `index`.
152
+ def at(index, options = {})
153
+ slice(index..index, options).first
154
+ end
155
+
156
+ # @return [String] member with the lowest index
157
+ def first(count = 0)
158
+ if count > 0
159
+ slice(0..(count-1), :with_scores => false)
160
+ else
161
+ at(0, :with_scores => false)
162
+ end
163
+ end
164
+
165
+ # @return [String] member with the highest index
166
+ def last(count = 0)
167
+ if count > 0
168
+ slice(-count..-1, :with_scores => false)
169
+ else
170
+ at(-1, :with_scores => false)
171
+ end
172
+ end
173
+
174
+ # @return [Float] the lowest score
175
+ def minimum
176
+ _, score = at(0); score
177
+ end
178
+
179
+ # @return [Float] the higest score
180
+ def maximum
181
+ _, score = at(-1); score
182
+ end
183
+
184
+ # Store the result of a union in a new +target+ key
185
+ # @param [Redpear::Store::Set] other
186
+ # The other set
187
+ # @param [multiple] others
188
+ # The other sets
189
+ # @param [Hash] options
190
+ # @option [Array] weights
191
+ # @option [Symbol] aggregate
192
+ # @return [Redpear::Store::Set] the result set
193
+ def unionstore(target, *others)
194
+ opts = others.last.is_a?(Hash) ? others.pop : {}
195
+ conn.zunionstore target.to_s, [key] + others.map(&:to_s), opts
196
+ self.class.new target.to_s, conn
197
+ end
198
+
199
+ # Store the result of an intersection in a new +target+ key
200
+ # @param [String] target
201
+ # The target key
202
+ # @param [multiple] others
203
+ # The other sets
204
+ # @param [Hash] options
205
+ # @option [Array] weights
206
+ # @option [Symbol] aggregate
207
+ # @return [Redpear::Store::SortedSet] the result set
208
+ def interstore(target, *others)
209
+ opts = others.last.is_a?(Hash) ? others.pop : {}
210
+ conn.zinterstore target.to_s, [key] + others.map(&:to_s), opts
211
+ self.class.new target.to_s, conn
212
+ end
213
+
214
+ # @param [String] member
215
+ # The member to increment
216
+ # @param [Integer] by
217
+ # The increment, defaults to 1
218
+ def increment(member, by = 1)
219
+ conn.zincrby(key, by, member).to_f
220
+ end
221
+
222
+ # @param [String] member
223
+ # The member to decrement
224
+ # @param [Integer] by
225
+ # The decrement, defaults to 1
226
+ def decrement(member, by = 1)
227
+ increment member, -by
228
+ end
229
+
230
+ private
231
+
232
+ def fetch_range(method, start, finish, options = {})
233
+ options[:limit] = [options[:offset] || 0, options[:limit]] if options[:offset] || options[:limit]
234
+ options[:with_scores] = true unless options.key?(:with_scores)
235
+ result = conn.send method, key, start, finish, options
236
+ options[:with_scores] ? result.each_slice(2).map {|m,s| [m, s.to_f] } : result
237
+ end
238
+
239
+ end
@@ -0,0 +1,66 @@
1
+ class Redpear::Store::Value < Redpear::Store::Base
2
+
3
+ # Deletes the value
4
+ # @see Redpear::Store::Base#purge!
5
+ alias_method :delete, :purge!
6
+
7
+ # @return [String] the value
8
+ def get
9
+ conn.get(key)
10
+ end
11
+
12
+ # @see #get
13
+ def value
14
+ get
15
+ end
16
+
17
+ # Sets the value
18
+ # @param [String] the value to set
19
+ def set(value)
20
+ conn.set(key, value)
21
+ end
22
+
23
+ # @see #set
24
+ def value=(*a)
25
+ set(*a)
26
+ end
27
+
28
+ # @see #set
29
+ def replace(*a)
30
+ set(*a)
31
+ end
32
+
33
+ # Appends a `value`
34
+ # @param [Integer] value
35
+ # The value to append
36
+ def append(value)
37
+ conn.append(key, value)
38
+ self
39
+ end
40
+ alias_method :<<, :append
41
+
42
+ # Comparator
43
+ # @param [String] other
44
+ # @return [Boolean] true, if equals `other`
45
+ def ==(other)
46
+ value == other
47
+ end
48
+
49
+ # @return [Boolean] true, if value is nil
50
+ def nil?
51
+ value.nil?
52
+ end
53
+
54
+ # @return [Boolean] true, if responds to `method`
55
+ def respond_to?(method, *a)
56
+ super || (value || "").respond_to?(method, *a)
57
+ end
58
+
59
+ protected
60
+
61
+ def method_missing(method, *a, &b)
62
+ base = (value || "")
63
+ base.respond_to?(method) ? base.send(method, *a, &b) : super
64
+ end
65
+
66
+ end
@@ -0,0 +1,11 @@
1
+ module Redpear::Store
2
+ autoload :Base, 'redpear/store/base'
3
+ autoload :Counter, 'redpear/store/counter'
4
+ autoload :Enumerable, 'redpear/store/enumerable'
5
+ autoload :Hash, 'redpear/store/hash'
6
+ autoload :List, 'redpear/store/list'
7
+ autoload :Lock, 'redpear/store/lock'
8
+ autoload :Set, 'redpear/store/set'
9
+ autoload :SortedSet, 'redpear/store/sorted_set'
10
+ autoload :Value, 'redpear/store/value'
11
+ end
data/lib/redpear.rb CHANGED
@@ -1,27 +1,12 @@
1
1
  require "redis"
2
2
  require "date"
3
+ require "set"
4
+ require "securerandom"
3
5
 
4
6
  module Redpear
5
-
6
- def self.autoload(const, path = nil)
7
- path ||= "redpear/#{const.to_s.downcase}"
8
- super const, path
9
- end
10
-
11
- autoload :Column
12
- autoload :Concern
13
- autoload :Connection
14
- autoload :Counters
15
- autoload :Expiration
16
- autoload :Finders
17
- autoload :Index
18
- autoload :Members
19
- autoload :Model
20
- autoload :Namespace
21
- autoload :Nest
22
- autoload :Persistence
23
- autoload :Schema
24
- autoload :ZIndex
25
- autoload :ZMembers
26
-
7
+ autoload :Concern, "redpear/concern"
8
+ autoload :Connection, "redpear/connection"
9
+ autoload :Model, "redpear/model"
10
+ autoload :Schema, "redpear/schema"
11
+ autoload :Store, "redpear/store"
27
12
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redpear
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-06 00:00:00.000000000Z
12
+ date: 2012-01-31 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &27432700 !ruby/object:Gem::Requirement
16
+ requirement: &22040360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *27432700
24
+ version_requirements: *22040360
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &27432320 !ruby/object:Gem::Requirement
27
+ requirement: &22039760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *27432320
35
+ version_requirements: *22039760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bundler
38
- requirement: &27431860 !ruby/object:Gem::Requirement
38
+ requirement: &22038240 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *27431860
46
+ version_requirements: *22038240
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &27461340 !ruby/object:Gem::Requirement
49
+ requirement: &22036720 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *27461340
57
+ version_requirements: *22036720
58
58
  - !ruby/object:Gem::Dependency
59
- name: fakeredis
60
- requirement: &27460920 !ruby/object:Gem::Requirement
59
+ name: shoulda-matchers
60
+ requirement: &22035080 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,21 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *27460920
68
+ version_requirements: *22035080
69
69
  - !ruby/object:Gem::Dependency
70
- name: shoulda-matchers
71
- requirement: &27460500 !ruby/object:Gem::Requirement
70
+ name: machinist
71
+ requirement: &22033100 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *22033100
80
+ - !ruby/object:Gem::Dependency
81
+ name: factory_girl
82
+ requirement: &22032660 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ! '>='
@@ -76,7 +87,7 @@ dependencies:
76
87
  version: '0'
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *27460500
90
+ version_requirements: *22032660
80
91
  description: Simple, elegant & efficient ORM for Redis
81
92
  email: dimitrij@blacksquaremedia.com
82
93
  executables: []
@@ -85,23 +96,27 @@ extra_rdoc_files: []
85
96
  files:
86
97
  - lib/redpear.rb
87
98
  - lib/redpear/connection.rb
99
+ - lib/redpear/schema/column.rb
100
+ - lib/redpear/schema/index.rb
88
101
  - lib/redpear/schema/collection.rb
89
- - lib/redpear/core_ext/stringify_keys.rb
102
+ - lib/redpear/schema/score.rb
90
103
  - lib/redpear/concern.rb
91
- - lib/redpear/zmembers.rb
92
- - lib/redpear/namespace.rb
93
- - lib/redpear/nest.rb
94
- - lib/redpear/finders.rb
95
- - lib/redpear/zindex.rb
96
- - lib/redpear/persistence.rb
97
- - lib/redpear/expiration.rb
98
- - lib/redpear/column.rb
104
+ - lib/redpear/store.rb
105
+ - lib/redpear/model/factory_girl.rb
106
+ - lib/redpear/model/finders.rb
107
+ - lib/redpear/model/expiration.rb
108
+ - lib/redpear/model/machinist.rb
109
+ - lib/redpear/store/lock.rb
110
+ - lib/redpear/store/enumerable.rb
111
+ - lib/redpear/store/counter.rb
112
+ - lib/redpear/store/hash.rb
113
+ - lib/redpear/store/base.rb
114
+ - lib/redpear/store/value.rb
115
+ - lib/redpear/store/list.rb
116
+ - lib/redpear/store/set.rb
117
+ - lib/redpear/store/sorted_set.rb
99
118
  - lib/redpear/model.rb
100
- - lib/redpear/index.rb
101
- - lib/redpear/members.rb
102
119
  - lib/redpear/schema.rb
103
- - lib/redpear/counters.rb
104
- - lib/redpear/machinist.rb
105
120
  homepage: https://github.com/bsm/redpear
106
121
  licenses: []
107
122
  post_install_message:
@@ -113,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
128
  requirements:
114
129
  - - ! '>='
115
130
  - !ruby/object:Gem::Version
116
- version: 1.8.7
131
+ version: 1.9.2
117
132
  required_rubygems_version: !ruby/object:Gem::Requirement
118
133
  none: false
119
134
  requirements:
@@ -1,17 +0,0 @@
1
- # Hash stringify_keys extension. "Borrowed" from ActiveSupport.
2
- class Hash
3
-
4
- # Return a new hash with all keys converted to strings.
5
- def stringify_keys
6
- dup.stringify_keys!
7
- end
8
-
9
- # Destructively convert all keys to strings.
10
- def stringify_keys!
11
- keys.each do |key|
12
- self[key.to_s] = delete(key) unless key.is_a?(String)
13
- end
14
- self
15
- end
16
-
17
- end unless Hash.new.respond_to?(:symbolize_keys)
@@ -1,26 +0,0 @@
1
- module Redpear::Counters
2
-
3
- # Increments the value of a counter attribute
4
- # @param [String|Symbol] column
5
- # The column name to increment
6
- # @param [Integer] by
7
- # Increment by this value
8
- def increment!(column, by = 1)
9
- return false unless persisted?
10
-
11
- col = self.class.columns[column]
12
- return false unless col && col.type == :counter
13
-
14
- self[col.name] = nest.hincrby(col.name, by).to_i
15
- end
16
-
17
- # Decrements the value of a counter attribute
18
- # @param [String|Symbol] column
19
- # The column name to decrement
20
- # @param [Integer] by
21
- # Decrement by this value
22
- def decrement!(column, by = 1)
23
- increment!(column, -by)
24
- end
25
-
26
- end