easyredis 0.0.3 → 0.0.4

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.
Files changed (6) hide show
  1. data/README.md +27 -8
  2. data/Rakefile +16 -17
  3. data/easyredis.gemspec +2 -5
  4. data/lib/easyredis.rb +154 -75
  5. data/tests/test.rb +1 -1
  6. metadata +2 -13
data/README.md CHANGED
@@ -6,18 +6,21 @@ Redis is a very fast key-value store that supports data structures like lists, (
6
6
 
7
7
  ## Installation
8
8
 
9
- You can get the source with git:
9
+ You can just grab the gem and you're good to go:
10
+
11
+ $ gem install easyredis
12
+
13
+ Or, you can get the source with git:
10
14
 
11
15
  $ git clone git://github.com/alecbenzer/easyredis.git
12
16
 
13
17
  or just download and extract a tar archive with the Downloads button.
14
18
 
15
- Once you have the source, run:
19
+ Once you have the source, you can run:
16
20
 
17
- $ rake
18
- $ gem install pkg/easyredis-x.x.x.gem
19
-
20
- Where x.x.x is the current version number.
21
+ $ rake manifest
22
+ $ rake build_gemspec
23
+ $ rake install easyredis.gemspec
21
24
 
22
25
  ## Basics
23
26
 
@@ -69,5 +72,21 @@ We can now sort our posts by title:
69
72
 
70
73
  And also search:
71
74
 
72
- Post.search_by(:title,"A common title") # all posts with this title
73
- Post.find_by(:title,"My First Post") # just one post
75
+ Post.search_by :title, "A common title" # all posts with this title
76
+ Post.find_by :title, "My First Post" # just one post
77
+
78
+ ## Text Search and Completions
79
+
80
+ We could have defined Post like this:
81
+
82
+ class Post < EasyRedis::Model
83
+ field :title
84
+ field :body
85
+
86
+ text_search :title
87
+ end
88
+
89
+ Now we can perform text searches and completions against our title field:
90
+
91
+ Post.matches(:title,"Fir") # titles that begin with "Fir"
92
+ Post.match(:title,"First") # posts whose titles contain "First"
data/Rakefile CHANGED
@@ -2,21 +2,20 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('easyredis','0.0.3') do |p|
5
+ Echoe.new('easyredis','0.0.4') do |p|
6
6
  p.description = "simple framework designed to make using redis as a database simpler"
7
7
  p.url = "https://github.com/alecbenzer/easyredis"
8
8
  p.author = "Alec Benzer"
9
9
  p.email = "alecbezer @nospam@ gmail.com"
10
10
  p.ignore_pattern = ["*.rdb"]
11
- p.development_dependencies = ["redis >=2.1.1","activesupport >=3.0.0"]
11
+ p.development_dependencies = ["redis >=2.1.1"]
12
12
  end
13
13
 
14
14
 
15
15
  require 'benchmark'
16
16
  require './tests/test'
17
17
 
18
- def rand_name
19
- length = 2
18
+ def rand_name(length=2)
20
19
  chars = []
21
20
  length.times { chars << (rand(26) + 65).chr }
22
21
  chars.join
@@ -26,17 +25,17 @@ end
26
25
  namespace :bm do
27
26
  task :clear do
28
27
  puts "destroying #{Man.count} previous entries"
29
- Benchmark.bm do |bm|
30
- bm.report { Man.destroy_all }
31
- end
28
+ time = Benchmark.measure { Man.destroy_all }
29
+ puts time.format
32
30
  end
33
31
 
34
32
  task :add do
35
33
  count = ENV["count"] ? ENV["count"].to_i : 25000
36
34
  puts "adding #{count} new entries"
37
35
  time = Benchmark::Tms.new
36
+ length = Math.log(3*count,26).round
38
37
  count.times do
39
- name = rand_name
38
+ name = rand_name(length)
40
39
  age = rand(100)
41
40
  time += Benchmark.measure { m = Man.new ; m.name = name ; m.age = age }
42
41
  end
@@ -48,9 +47,10 @@ namespace :bm do
48
47
  task :search do
49
48
  puts "searching #{Man.count} entries by a particular name"
50
49
  name = Man.rand.name
51
- Benchmark.bm do |bm|
52
- bm.report { Man.search_by(:name,name) }
53
- end
50
+ count = -1
51
+ time = Benchmark.measure { count = Man.search_by(:name,name).count }
52
+ puts "retrived #{count} records in:"
53
+ puts (time*1000).format
54
54
  end
55
55
 
56
56
  task :singlesearch do
@@ -60,9 +60,9 @@ namespace :bm do
60
60
  t1 = Benchmark.measure { Man.search(:age => age) }
61
61
  t2 = Benchmark.measure { Man.search_by(:age,age) }
62
62
  puts "Model#search:"
63
- puts t1.format
63
+ puts (t1*1000).format
64
64
  puts "Model#search_by:"
65
- puts t2.format
65
+ puts (t2*1000).format
66
66
  puts "search is #{((t1.real/t2.real) - 1)*100}% slower"
67
67
  end
68
68
 
@@ -73,15 +73,14 @@ namespace :bm do
73
73
  count = 0
74
74
  time = Benchmark.measure { count = Man.search(:name => name, :age => age).size }
75
75
  puts "retrived #{count} out of #{Man.count} entries in:"
76
- puts time.format
76
+ puts (time*1000).format
77
77
  end
78
78
 
79
79
  task :find do
80
80
  puts "finding one of #{Man.count} entries by name"
81
81
  name = Man.rand.name
82
- Benchmark.bm do |bm|
83
- bm.report { Man.find_by(:name,name) }
84
- end
82
+ time = Benchmark.measure { Man.find_by(:name,name) }
83
+ puts (time*1000).format
85
84
  end
86
85
 
87
86
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{easyredis}
5
- s.version = "0.0.3"
5
+ s.version = "0.0.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Alec Benzer"]
9
- s.date = %q{2011-02-06}
9
+ s.date = %q{2011-02-07}
10
10
  s.description = %q{simple framework designed to make using redis as a database simpler}
11
11
  s.email = %q{alecbezer @nospam@ gmail.com}
12
12
  s.extra_rdoc_files = ["README.md", "lib/easyredis.rb"]
@@ -23,13 +23,10 @@ Gem::Specification.new do |s|
23
23
 
24
24
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
25
  s.add_development_dependency(%q<redis>, [">= 2.1.1"])
26
- s.add_development_dependency(%q<activesupport>, [">= 3.0.0"])
27
26
  else
28
27
  s.add_dependency(%q<redis>, [">= 2.1.1"])
29
- s.add_dependency(%q<activesupport>, [">= 3.0.0"])
30
28
  end
31
29
  else
32
30
  s.add_dependency(%q<redis>, [">= 2.1.1"])
33
- s.add_dependency(%q<activesupport>, [">= 3.0.0"])
34
31
  end
35
32
  end
@@ -7,7 +7,6 @@
7
7
 
8
8
  require 'redis'
9
9
  require 'set'
10
- require 'active_support/inflector'
11
10
 
12
11
 
13
12
  # main EasyRedis module which
@@ -16,6 +15,9 @@ module EasyRedis
16
15
 
17
16
  # generate a 'score' for a string
18
17
  # used for storing it in a sorted set
18
+ #
19
+ # This method effectively turns a string into a base 27 floating point number,
20
+ # where 0 corresponds to no letter, 1 to A, 2 to B, etc.
19
21
  def self.string_score(str)
20
22
  str = str.downcase
21
23
  mult = 1.0
@@ -29,11 +31,19 @@ module EasyRedis
29
31
 
30
32
  # gets a score for a generic object
31
33
  #
32
- # Uses EasyRedis#string_score if the object is a string,
33
- # and just returns the object otherwise (presumably its a number)
34
+ # The score is determined as follows:
35
+ # First, if the object is a string, string_score is used to get its score.
36
+ # Otherwise, we try calling the following methods on the object in turn, returning the first that works: score, to_f, to_i.
37
+ # If none of those work, we simply return the object itself.
34
38
  def self.score(obj)
35
39
  if obj.is_a? String
36
40
  string_score(obj)
41
+ elsif obj.respond_to? "score"
42
+ obj.score
43
+ elsif obj.respond_to? "to_f"
44
+ obj.to_f
45
+ elsif obj.respond_to? "to_i"
46
+ obj.to_i
37
47
  else
38
48
  obj
39
49
  end
@@ -62,6 +72,17 @@ module EasyRedis
62
72
  end
63
73
  end
64
74
 
75
+ # exception that indicates that the given field has not been indexed for text-searching
76
+ class FieldNotTextSearchable < RuntimeError
77
+ def initialize(field)
78
+ @message = "field '#{field.to_s}' not text-searchable"
79
+ end
80
+
81
+ def to_s
82
+ @message
83
+ end
84
+ end
85
+
65
86
  # exception that indicated an unknown ordering option was encountered
66
87
  class UnknownOrderOption < RuntimeError
67
88
  def initialize(opt)
@@ -73,23 +94,14 @@ module EasyRedis
73
94
  end
74
95
  end
75
96
 
76
- # class representing a sort
77
- class Sort
97
+ # class representing a generic collection
98
+ class Collection
78
99
  include Enumerable
79
100
 
80
- # initialize the sort with a specific field, ordering option, and model
81
- def initialize(field,order,klass)
82
- raise EasyRedis::FieldNotSortable, field unless klass.sortable?(field)
83
- raise EasyRedis::UnknownOrderOption, order unless [:asc,:desc].member? order
84
- @field = field
85
- @order = order
86
- @klass = klass
87
- end
88
-
89
101
  # access elements in this sort
90
102
  #
91
- # Work's like ruby's Array#[]. It can take a specific index, a range, or an offset, amount pair.
92
- # Calling this method will actually query the redis server for ids
103
+ # Work's like an Array's [] method. It can take a specific index, a range, or an offset and an amount/limit.
104
+ # This method uses the underlying access method, which handles the actual retrival.
93
105
  def [](index,limit=nil)
94
106
  if limit
95
107
  offset = index
@@ -101,36 +113,12 @@ module EasyRedis
101
113
  end
102
114
  end
103
115
 
104
- # helper method for []
105
- #
106
- # takes a range and returns corresponding elements
107
- def access(range)
108
- a = range.begin
109
- b = range.end
110
- b -= 1 if index.exclude_end?
111
- ids = []
112
- if @order == :asc
113
- ids = EasyRedis.redis.zrange(@klass.sort_prefix(@field),a,b)
114
- elsif @order == :desc
115
- ids = EasyRedis.redis.zrevrange(@klass.sort_prefix(@field),a,b)
116
- end
117
- ids.map{|i|@klass.new(i)}
118
- end
119
-
120
- # iterate through all members of this sort
116
+ # iterate through all members of this collection
121
117
  def each
122
118
  self[0..-1].each { |o| yield o }
123
119
  end
124
120
 
125
- # return the number of elements in this sort
126
- #
127
- # As of now, idential to the Model's #count method.
128
- # This method is explicility defined here to overwrite the default one in Enumerable, which iterates through all the entries to count them
129
- def count
130
- EasyRedis.zcard(@klass.sort_prefix(@field))
131
- end
132
-
133
- # return the fist element of this sort, or the first n elements, if n is given
121
+ # return the fist element of this collection, or the first n elements, if n is given
134
122
  def first(n = nil)
135
123
  if n
136
124
  self[0,n]
@@ -139,6 +127,7 @@ module EasyRedis
139
127
  end
140
128
  end
141
129
 
130
+ # return the last element of this collection, or the last n elements, if n is given
142
131
  def last(n = nil)
143
132
  if n
144
133
  self[-n..-1]
@@ -147,16 +136,66 @@ module EasyRedis
147
136
  end
148
137
  end
149
138
 
139
+ private
140
+
141
+ # access the elements corresponding to the given range
142
+ #
143
+ # meant to be overridden in child classes
144
+ def access(range)
145
+ []
146
+ end
147
+
148
+ end
149
+
150
+ # class representing a sort
151
+ class Sort < Collection
152
+
153
+ # initialize the sort with a specific field, ordering option, and model
154
+ def initialize(field,order,klass)
155
+ raise EasyRedis::FieldNotSortable, field unless klass.sortable?(field)
156
+ raise EasyRedis::UnknownOrderOption, order unless [:asc,:desc].member? order
157
+ @field = field
158
+ @order = order
159
+ @klass = klass
160
+ end
161
+
162
+ # return the number of elements in this sort
163
+ #
164
+ # As of now, idential to the Model's count method.
165
+ # This method is explicility defined here to overwrite the default one in Enumerable, which iterates through all the entries to count them, which is much slower than a ZCARD command
166
+ def count
167
+ EasyRedis.zcard(@klass.sort_key(@field))
168
+ end
169
+
150
170
  def inspect
151
171
  "#<EasyRedis::Sort model=#{@klass.name}, field=#{@field.to_s}, order=#{@order.to_s}>"
152
172
  end
153
173
 
174
+ private
175
+
176
+ # takes a range and returns corresponding elements
177
+ def access(range)
178
+ a = range.begin
179
+ b = range.end
180
+ b -= 1 if range.exclude_end?
181
+ ids = []
182
+ if @order == :asc
183
+ ids = EasyRedis.redis.zrange(@klass.sort_key(@field),a,b)
184
+ elsif @order == :desc
185
+ ids = EasyRedis.redis.zrevrange(@klass.sort_key(@field),a,b)
186
+ end
187
+ ids.map{|i|@klass.new(i)}
188
+ end
189
+
154
190
  end
155
191
 
156
192
 
157
193
  # class representing a data model
158
194
  # you want to store in redis
159
195
  class Model
196
+
197
+ @@sorts = []
198
+ @@text_searches = []
160
199
 
161
200
  # add a field to the model
162
201
  def self.field(name)
@@ -180,22 +219,33 @@ module EasyRedis
180
219
  EasyRedis.redis.hset(key_name,name,Marshal.dump(val))
181
220
  instance_variable_set(instance_var,val)
182
221
 
183
- if @@sorts.member? name.to_sym
184
- # score = val.is_a?(String) ? EasyRedis.string_score(val) : val
185
- EasyRedis.redis.zadd(sort_prefix(name),EasyRedis.score(val),@id)
222
+ if self.class.sortable? name.to_sym
223
+ EasyRedis.redis.zadd(sort_key(name),EasyRedis.score(val),@id)
224
+ end
225
+
226
+ if self.class.text_search? name.to_sym
227
+ val.split.each do |term|
228
+ EasyRedis.redis.zadd term_key(name,term), created_at.to_i, id
229
+ EasyRedis.redis.zadd terms_key(name), EasyRedis.score(term), term
230
+ end
186
231
  end
187
232
  end
188
233
  end
189
234
 
190
235
  # index a field to be sorted/searched
191
236
  def self.sort_on(field)
192
- @@sorts ||= []
193
237
  @@sorts << field.to_sym
194
238
  end
195
239
 
240
+ # index a field for text searching
241
+ def self.text_search(field)
242
+ @@text_searches << field.to_sym
243
+ sort_on(field) unless sortable? field
244
+ end
245
+
196
246
  # returns number of instances of this model
197
247
  def self.count
198
- EasyRedis.redis.zcard(prefix.pluralize)
248
+ EasyRedis.redis.zcard(prefix)
199
249
  end
200
250
 
201
251
  # get all instances of this model
@@ -204,27 +254,33 @@ module EasyRedis
204
254
  self.sort_by :created_at, options
205
255
  end
206
256
 
257
+ # same as all.first
207
258
  def self.first(n = nil)
208
259
  self.all.first(n)
209
260
  end
210
261
 
262
+ # same as all.last
211
263
  def self.last(n = nil)
212
264
  self.all.last(n)
213
265
  end
214
266
 
267
+ # returns a random entry of this model
215
268
  def self.rand
216
269
  self[Kernel.rand(self.count)]
217
270
  end
218
271
 
219
272
  # find an instance of this model based on its id
220
273
  def self.find(id)
221
- if EasyRedis.redis.zscore(prefix.pluralize,id)
274
+ if EasyRedis.redis.zscore(prefix,id)
222
275
  new(id)
223
276
  else
224
277
  nil
225
278
  end
226
279
  end
227
280
 
281
+ # access entries of this model based on time
282
+ #
283
+ # same as all.[]
228
284
  def self.[](index,amt=nil)
229
285
  self.all[index,amt]
230
286
  end
@@ -234,7 +290,7 @@ module EasyRedis
234
290
  raise EasyRedis::FieldNotSortable, field unless @@sorts.member? field.to_sym
235
291
  scr = EasyRedis.score(val)
236
292
  # options[:limit] = [0,options[:limit]] if options[:limit]
237
- ids = EasyRedis.redis.zrangebyscore(sort_prefix(field),scr,scr,proc_options(options))
293
+ ids = EasyRedis.redis.zrangebyscore(sort_key(field),scr,scr,proc_options(options))
238
294
  ids.map{|i| new(i) }
239
295
  end
240
296
 
@@ -243,12 +299,15 @@ module EasyRedis
243
299
  search_by(field,val,:limit => 1).first
244
300
  end
245
301
 
302
+ # search the model based on multiple parameters
303
+ #
304
+ # takes a hash of field => value pairs
246
305
  def self.search(params)
247
306
  return search_by(*params.first) if params.size == 1 # comment out for benchmarking purposes
248
307
  result_set = nil
249
308
  params.each do |field,value|
250
309
  scr = EasyRedis.score(value)
251
- ids = EasyRedis.redis.zrangebyscore(sort_prefix(field),scr,scr)
310
+ ids = EasyRedis.redis.zrangebyscore(sort_key(field),scr,scr)
252
311
  result_set = result_set ? (result_set & Set.new(ids)) : Set.new(ids)
253
312
  end
254
313
  result_set.map{|i|new(i)}
@@ -259,39 +318,42 @@ module EasyRedis
259
318
  EasyRedis::Sort.new(field,options[:order],self)
260
319
  end
261
320
 
262
- # gives all values for the given field that begins with str
321
+ # gives all values for the given field that begin with str
263
322
  #
264
- # This method is currently iterates through all existing entries. It is therefore very slow and should probably not be used at this time.
323
+ # The field must have been indexed with text_search.
265
324
  def self.matches(field,str)
325
+ raise FieldNotTextSearchable, field unless self.text_search? field
266
326
  scr = EasyRedis.score(str)
267
327
  a,b = scr, scr+1/(27.0**str.size)
268
- ids = EasyRedis.redis.zrangebyscore(sort_prefix(field), "#{a}", "(#{b}")
269
- s = Set.new
270
- ids.each{|i| s << new(i).send(field.to_s) }
271
- s.to_a
328
+ EasyRedis.redis.zrangebyscore(terms_key(field), "#{a}", "(#{b}")
272
329
  end
273
330
 
274
- # searches for all entries where field begins with str
331
+ # searches for all entries where field contains the string str
275
332
  #
276
- # works with string fields that have been indexed with sort_on
333
+ # The string must appear exactly as a term in field's value. To search based on the beginning of a term, you can combine this method with matches.
334
+ # The field must have been indexed with text_search.
277
335
  def self.match(field,str, options = {})
278
- raise EasyRedis::FieldNotSortable, filename unless @@sorts.member? field
279
- scr = EasyRedis.score(str)
280
- a,b = scr, scr+1/(27.0**str.size)
281
- ids = EasyRedis.redis.zrangebyscore(sort_prefix(field), "#{a}", "(#{b}", proc_options(options))
336
+ raise EasyRedis::FieldNotTextSearchable, filename unless text_search? field
337
+ ids = EasyRedis.redis.zrange(term_key(field,str), 0, -1, proc_options(options))
282
338
  ids.map{|i| new(i)}
283
339
  end
284
340
 
285
341
  # indicates whether field has been indexed with sort_on
286
342
  def self.sortable?(field)
287
- @@sorts.member? field or field.to_sym == :created_at
343
+ @@sorts and (@@sorts.member? field or field.to_sym == :created_at)
344
+ end
345
+
346
+ # indicates whether field has been indexed with text_search
347
+ def self.text_search?(field)
348
+ @@text_searches and @@text_searches.member?(field)
288
349
  end
289
350
 
290
351
  # destroy all instances of this model
291
352
  def self.destroy_all
292
353
  all.each {|x| x.destroy}
293
- @@sorts.each {|field| EasyRedis.redis.del(sort_prefix(field)) }
294
- EasyRedis.redis.del(prefix.pluralize)
354
+ @@sorts.each {|field| EasyRedis.redis.del(sort_key(field)) }
355
+ @@text_searches.each {|field| EasyRedis.redis.del(terms_key(field)) }
356
+ EasyRedis.redis.del(prefix)
295
357
  EasyRedis.redis.del(prefix + ":next_id")
296
358
  end
297
359
 
@@ -303,20 +365,20 @@ module EasyRedis
303
365
  #
304
366
  # If no id is passed, one is generated for you.
305
367
  # Otherwise, sets the id field to the passed id, but does not check to see if it is a valid id for this model.
306
- # Users should use Model#find or Model#[] when retiving models by id, as these check for valid ids.
368
+ # Users should use find when retiving models by id, as these check for valid ids.
307
369
  def initialize(id=nil)
308
370
  if id
309
371
  @id = id
310
372
  else
311
373
  @id = EasyRedis.redis.incr(prefix + ':next_id')
312
- EasyRedis.redis.zadd(prefix.pluralize,Time.now.to_i,@id)
374
+ EasyRedis.redis.zadd(prefix,Time.now.to_i,@id)
313
375
  @id
314
376
  end
315
377
  end
316
378
 
317
379
  # get the creation time of an entry
318
380
  def created_at
319
- Time.at(EasyRedis.redis.zscore(prefix.pluralize,@id).to_i)
381
+ Time.at(EasyRedis.redis.zscore(prefix,@id).to_i)
320
382
  end
321
383
 
322
384
  # directly access a field of this entry's redis hash
@@ -339,7 +401,7 @@ module EasyRedis
339
401
 
340
402
  # remove the entry
341
403
  def destroy
342
- EasyRedis.redis.zrem(prefix.pluralize,@id)
404
+ EasyRedis.redis.zrem(prefix,@id)
343
405
  EasyRedis.redis.del(key_name)
344
406
  end
345
407
 
@@ -362,8 +424,9 @@ module EasyRedis
362
424
 
363
425
  private
364
426
 
427
+ # generate a temporary key name associated with this model
365
428
  def self.get_temp_key
366
- i = EasyRedis.redis.incr prefix.pluralize + ':next_tmp_id'
429
+ i = EasyRedis.redis.incr "#{prefix}:next_tmp_id"
367
430
  "#{name}:tmp_#{i}"
368
431
  end
369
432
 
@@ -377,20 +440,36 @@ module EasyRedis
377
440
  self.name.downcase
378
441
  end
379
442
 
380
- def self.sort_prefix(field)
443
+ def self.sort_key(field)
381
444
  if field == :created_at
382
- prefix.pluralize
445
+ prefix
383
446
  else
384
- prefix.pluralize + ':sort_' + field.to_s
447
+ "#{prefix}:sort_#{field.to_s}"
385
448
  end
386
449
  end
387
450
 
451
+ def self.terms_key(field)
452
+ "#{prefix}:terms_#{field.to_s}"
453
+ end
454
+
455
+ def self.term_key(field,term)
456
+ "#{prefix}:term_#{field}:#{term}"
457
+ end
458
+
388
459
  def prefix
389
460
  self.class.prefix
390
461
  end
391
462
 
392
- def sort_prefix(field)
393
- self.class.sort_prefix(field)
463
+ def sort_key(field)
464
+ self.class.sort_key(field)
465
+ end
466
+
467
+ def terms_key(field)
468
+ self.class.terms_key(field)
469
+ end
470
+
471
+ def term_key(field,term)
472
+ self.class.term_key(field,term)
394
473
  end
395
474
  end
396
475
  end
@@ -4,7 +4,7 @@ class Man < EasyRedis::Model
4
4
  field :name
5
5
  field :age
6
6
 
7
- sort_on :name
7
+ text_search :name
8
8
  sort_on :age
9
9
  end
10
10
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: easyredis
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.3
5
+ version: 0.0.4
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alec Benzer
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-02-06 00:00:00 -05:00
13
+ date: 2011-02-07 00:00:00 -05:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -24,17 +24,6 @@ dependencies:
24
24
  version: 2.1.1
25
25
  type: :development
26
26
  version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
- prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
31
- none: false
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: 3.0.0
36
- type: :development
37
- version_requirements: *id002
38
27
  description: simple framework designed to make using redis as a database simpler
39
28
  email: alecbezer @nospam@ gmail.com
40
29
  executables: []