redis-objects 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ class Redis
2
+ module Objects
3
+ VERSION = "0.8.0"
4
+ end
5
+ end
@@ -115,14 +115,20 @@ class Redis
115
115
  from_redis redis.zrangebyscore(key, min, max, args)
116
116
  end
117
117
 
118
- # Forwards compat (not yet implemented in Redis)
119
- def revrangebyscore(min, max, options={})
118
+ # Returns all the elements in the sorted set at key with a score between max and min
119
+ # (including elements with score equal to max or min). In contrary to the default ordering of sorted sets,
120
+ # for this command the elements are considered to be ordered from high to low scores.
121
+ # Options:
122
+ # :count, :offset - passed to LIMIT
123
+ # :withscores - if true, scores are returned as well
124
+ # Redis: ZREVRANGEBYSCORE
125
+ def revrangebyscore(max, min, options={})
120
126
  args = {}
121
127
  args[:limit] = [options[:offset] || 0, options[:limit] || options[:count]] if
122
128
  options[:offset] || options[:limit] || options[:count]
123
129
  args[:with_scores] = true if options[:withscores] || options[:with_scores]
124
130
 
125
- from_redis redis.zrevrangebyscore(key, min, max, args)
131
+ from_redis redis.zrevrangebyscore(key, max, min, args)
126
132
  end
127
133
 
128
134
  # Remove all elements in the sorted set at key with rank between start and end. Start and end are
@@ -160,14 +166,14 @@ class Redis
160
166
  # Increment the rank of that member atomically and return the new value. This
161
167
  # method is aliased as incr() for brevity. Redis: ZINCRBY
162
168
  def increment(member, by=1)
163
- redis.zincrby(key, by, member).to_i
169
+ redis.zincrby(key, by, to_redis(member)).to_i
164
170
  end
165
171
  alias_method :incr, :increment
166
172
  alias_method :incrby, :increment
167
173
 
168
174
  # Convenience to calling increment() with a negative number.
169
175
  def decrement(member, by=1)
170
- redis.zincrby(key, -by, member).to_i
176
+ redis.zincrby(key, -by, to_redis(member)).to_i
171
177
  end
172
178
  alias_method :decr, :decrement
173
179
  alias_method :decrby, :decrement
@@ -1,76 +1,30 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'redis/objects/version'
5
5
 
6
- Gem::Specification.new do |s|
7
- s.name = "redis-objects"
8
- s.version = "0.7.0"
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "redis-objects"
8
+ spec.version = Redis::Objects::VERSION
9
+ spec.authors = ["Nate Wiger"]
10
+ spec.email = ["nwiger@gmail.com"]
11
+ spec.description = %q{Map Redis types directly to Ruby objects. Works with any class or ORM.}
12
+ spec.summary = %q{Map Redis types directly to Ruby objects}
13
+ spec.homepage = "http://github.com/nateware/redis-objects"
14
+ spec.license = "Artistic"
9
15
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Nate Wiger"]
12
- s.date = "2013-02-27"
13
- s.description = "Map Redis types directly to Ruby objects. Works with any class or ORM."
14
- s.email = "nwiger@gmail.com"
15
- s.extra_rdoc_files = [
16
- "README.md"
17
- ]
18
- s.files = [
19
- "ATOMICITY.rdoc",
20
- "CHANGELOG.rdoc",
21
- "Gemfile",
22
- "README.md",
23
- "Rakefile",
24
- "VERSION",
25
- "lib/redis-objects.rb",
26
- "lib/redis/base_object.rb",
27
- "lib/redis/counter.rb",
28
- "lib/redis/hash_key.rb",
29
- "lib/redis/helpers/core_commands.rb",
30
- "lib/redis/helpers/serialize.rb",
31
- "lib/redis/list.rb",
32
- "lib/redis/lock.rb",
33
- "lib/redis/objects.rb",
34
- "lib/redis/objects/counters.rb",
35
- "lib/redis/objects/hashes.rb",
36
- "lib/redis/objects/lists.rb",
37
- "lib/redis/objects/locks.rb",
38
- "lib/redis/objects/sets.rb",
39
- "lib/redis/objects/sorted_sets.rb",
40
- "lib/redis/objects/values.rb",
41
- "lib/redis/set.rb",
42
- "lib/redis/sorted_set.rb",
43
- "lib/redis/value.rb",
44
- "redis-objects.gemspec",
45
- "spec/redis_autoload_objects_spec.rb",
46
- "spec/redis_namespace_compat_spec.rb",
47
- "spec/redis_objects_active_record_spec.rb",
48
- "spec/redis_objects_conn_spec.rb",
49
- "spec/redis_objects_instance_spec.rb",
50
- "spec/redis_objects_model_spec.rb",
51
- "spec/spec_helper.rb"
52
- ]
53
- s.homepage = "http://github.com/nateware/redis-objects"
54
- s.require_paths = ["lib"]
55
- s.rubygems_version = "1.8.24"
56
- s.summary = "Map Redis types directly to Ruby objects"
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
57
20
 
58
- if s.respond_to? :specification_version then
59
- s.specification_version = 3
21
+ spec.add_dependency "redis", ">= 3.0.2"
60
22
 
61
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
62
- s.add_runtime_dependency(%q<redis>, [">= 3.0.2"])
63
- s.add_development_dependency(%q<bacon>, [">= 0"])
64
- s.add_development_dependency(%q<redis-namespace>, [">= 1.2.0"])
65
- else
66
- s.add_dependency(%q<redis>, [">= 3.0.2"])
67
- s.add_dependency(%q<bacon>, [">= 0"])
68
- s.add_dependency(%q<redis-namespace>, [">= 1.2.0"])
69
- end
70
- else
71
- s.add_dependency(%q<redis>, [">= 3.0.2"])
72
- s.add_dependency(%q<bacon>, [">= 0"])
73
- s.add_dependency(%q<redis-namespace>, [">= 1.2.0"])
74
- end
75
- end
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "bacon"
76
26
 
27
+ # compatability testing
28
+ spec.add_development_dependency "redis-namespace"
29
+ spec.add_development_dependency "activerecord", "~> 3.2"
30
+ end
@@ -8,7 +8,7 @@ describe Redis::Value do
8
8
  @value = Redis::Value.new('spec/value')
9
9
  @value.delete
10
10
  end
11
-
11
+
12
12
  it "should marshal default value" do
13
13
  @value = Redis::Value.new('spec/value', :default => {:json => 'data'}, :marshal => true)
14
14
  @value.value.should == {:json => 'data'}
@@ -30,7 +30,7 @@ describe Redis::Value do
30
30
  @value.should == nil
31
31
  @value.value = {:json => 'data'}
32
32
  @value.should == {:json => 'data'}
33
-
33
+
34
34
  # no marshaling
35
35
  @value.options[:marshal] = false
36
36
  v = {:json => 'data'}
@@ -171,6 +171,9 @@ describe Redis::List do
171
171
  @list.get.should == ['a','c','f']
172
172
  @list << 'j'
173
173
  @list.should == ['a','c','f','j']
174
+ @list.push 'h'
175
+ @list.push 'i', 'j'
176
+ @list.should == ['a','c','f','j','h','i','j']
174
177
  # Test against similar Ruby functionality
175
178
  a = @list.values
176
179
  @list[0..2].should == a[0..2]
@@ -184,34 +187,35 @@ describe Redis::List do
184
187
  @list.slice(1, 3).should == a.slice(1, 3)
185
188
  @list[0, 0].should == []
186
189
  @list[0, -1].should == a[0, -1]
187
- @list.length.should == 4
188
- @list.size.should == 4
190
+ @list.length.should == 7
189
191
  @list.should == a
190
192
  @list.get.should == a
193
+ @list.pop # lose 'j'
194
+ @list.size.should == 6
191
195
 
192
196
  i = -1
193
197
  @list.each do |st|
194
198
  st.should == @list[i += 1]
195
199
  end
196
- @list.should == ['a','c','f','j']
197
- @list.get.should == ['a','c','f','j']
200
+ @list.should == ['a','c','f','j','h','i']
201
+ @list.get.should == ['a','c','f','j','h','i']
198
202
 
199
203
  @list.each_with_index do |st,i|
200
204
  st.should == @list[i]
201
205
  end
202
- @list.should == ['a','c','f','j']
203
- @list.get.should == ['a','c','f','j']
206
+ @list.should == ['a','c','f','j','h','i']
207
+ @list.get.should == ['a','c','f','j','h','i']
204
208
 
205
209
  coll = @list.collect{|st| st}
206
- coll.should == ['a','c','f','j']
207
- @list.should == ['a','c','f','j']
208
- @list.get.should == ['a','c','f','j']
210
+ coll.should == ['a','c','f','j','h','i']
211
+ @list.should == ['a','c','f','j','h','i']
212
+ @list.get.should == ['a','c','f','j','h','i']
209
213
 
210
214
  @list << 'a'
211
215
  coll = @list.select{|st| st == 'a'}
212
216
  coll.should == ['a','a']
213
- @list.should == ['a','c','f','j','a']
214
- @list.get.should == ['a','c','f','j','a']
217
+ @list.should == ['a','c','f','j','h','i','a']
218
+ @list.get.should == ['a','c','f','j','h','i','a']
215
219
  end
216
220
 
217
221
  it "should handle rpoplpush" do
@@ -234,23 +238,42 @@ describe Redis::List do
234
238
  @list.should == ['z','a','b','c','d','e']
235
239
  end
236
240
 
241
+ it "should handle insert at a specific index" do
242
+ @list << 'b' << 'd'
243
+ @list.should == ['b','d']
244
+ @list[0] = 'a'
245
+ @list.should == ['a', 'd']
246
+ @list[1] = 'b'
247
+ @list.should == ['a', 'b']
248
+ end
249
+
237
250
  it "should handle lists of complex data types" do
238
251
  @list.options[:marshal] = true
239
252
  v1 = {:json => 'data'}
240
253
  v2 = {:json2 => 'data2'}
254
+ v3 = [1,2,3]
241
255
  @list << v1
242
256
  @list << v2
243
257
  @list.first.should == v1
258
+ @list[0] = @list[0].tap{|d| d[:json] = 'data_4'}
259
+ @list.first.should == {:json => 'data_4'}
244
260
  @list.last.should == v2
245
- @list << [1,2,3,[4,5]]
246
- @list.last.should == [1,2,3,[4,5]]
247
- @list.shift.should == {:json => 'data'}
261
+ @list << [1,2,3,[4,5],6]
262
+ @list.last.should == [1,2,3,[4,5],6]
263
+ @list.shift.should == {:json => 'data_4'}
248
264
  @list.size.should == 2
249
265
  @list.delete(v2)
250
266
  @list.size.should == 1
267
+ @list.push v1, v2
268
+ @list[1].should == v1
269
+ @list.last.should == v2
270
+ @list.size.should == 3
271
+ @list.unshift v2, v3
272
+ @list.size.should == 5
273
+ @list.first.should == v3
251
274
  @list.options[:marshal] = false
252
275
  end
253
-
276
+
254
277
  it "should support renaming lists" do
255
278
  @list.should.be.empty
256
279
  @list << 'a' << 'b' << 'a' << 3
@@ -292,7 +315,7 @@ describe Redis::Counter do
292
315
  @counter.key.should == 'spec/counter'
293
316
  @counter.incr(10)
294
317
  @counter.should == 10
295
-
318
+
296
319
  # math proxy ops
297
320
  (@counter == 10).should.be.true
298
321
  (@counter <= 10).should.be.true
@@ -446,13 +469,13 @@ describe Redis::HashKey do
446
469
  @hash = Redis::HashKey.new('test_hash')
447
470
  @hash.clear
448
471
  end
449
-
472
+
450
473
  it "should handle complex marshaled values" do
451
474
  @hash.options[:marshal] = true
452
475
  @hash['abc'].should == nil
453
476
  @hash['abc'] = {:json => 'data'}
454
477
  @hash['abc'].should == {:json => 'data'}
455
-
478
+
456
479
  # no marshaling
457
480
  @hash.options[:marshal] = false
458
481
  v = {:json => 'data'}
@@ -465,26 +488,26 @@ describe Redis::HashKey do
465
488
  @hash.fetch('abc').should == [[1,2], {:t3 => 4}]
466
489
  @hash.delete('abc').should == 1
467
490
  @hash.fetch('abc').should.be.nil
468
-
491
+
469
492
  @hash.options[:marshal] = true
470
493
  @hash.bulk_set('abc' => [[1,2], {:t3 => 4}], 'def' => [[6,8], {:t4 => 8}])
471
494
  hsh = @hash.bulk_get('abc', 'def', 'foo')
472
495
  hsh['abc'].should == [[1,2], {:t3 => 4}]
473
496
  hsh['def'].should == [[6,8], {:t4 => 8}]
474
497
  hsh['foo'].should.be.nil
475
-
498
+
476
499
  hsh = @hash.all
477
500
  hsh['abc'].should == [[1,2], {:t3 => 4}]
478
501
  hsh['def'].should == [[6,8], {:t4 => 8}]
479
-
480
- @hash.values.should == [[[1,2], {:t3 => 4}], [[6,8], {:t4 => 8}]]
481
-
502
+
503
+ @hash.values.sort.should == [[[1,2], {:t3 => 4}], [[6,8], {:t4 => 8}]].sort
504
+
482
505
  @hash.delete('def').should == 1
483
506
  @hash.delete('abc').should == 1
484
-
507
+
485
508
  @hash.options[:marshal] = false
486
509
  end
487
-
510
+
488
511
  it "should get and set values" do
489
512
  @hash['foo'] = 'bar'
490
513
  @hash['foo'].should == 'bar'
@@ -508,7 +531,7 @@ describe Redis::HashKey do
508
531
  val.should == 'bar'
509
532
  end
510
533
  end
511
-
534
+
512
535
  it "should have 1 item" do
513
536
  @hash['foo'] = 'bar'
514
537
  @hash.size.should == 1
@@ -539,7 +562,7 @@ describe Redis::HashKey do
539
562
  @hash.clear
540
563
  @hash.should.be.empty
541
564
  end
542
-
565
+
543
566
  it "should respond to bulk_set" do
544
567
  @hash.bulk_set({'abc' => 'xyz', 'bizz' => 'bazz'})
545
568
  @hash['abc'].should == 'xyz'
@@ -569,18 +592,20 @@ describe Redis::HashKey do
569
592
 
570
593
  it "should respond to fill" do
571
594
  @hash['foo'] = 'bar'
572
-
595
+
573
596
  @hash.fill('abc' => '123', 'bang' => 'michael')
574
597
  @hash['foo'].should == 'bar'
575
598
  @hash['abc'].should == '123'
576
599
  @hash['bang'].should == 'michael'
600
+
601
+ it "raises an error if a non-Hash is passed to fill" do
602
+ lambda { @hash.fill([]) }.should.raise(ArgumentError)
603
+ end
577
604
  end
578
-
579
605
 
580
606
  after do
581
607
  @hash.clear
582
608
  end
583
-
584
609
  end
585
610
 
586
611
  describe Redis::Set do
@@ -616,7 +641,7 @@ describe Redis::Set do
616
641
  @set.size.should == 2
617
642
  @set.delete('a')
618
643
  @set.pop.should == 'b'
619
-
644
+
620
645
  @set.add('a')
621
646
  @set.add('b')
622
647
 
@@ -641,7 +666,7 @@ describe Redis::Set do
641
666
  @set.delete_if{|m| m == 'c'}
642
667
  @set.sort.should == ['a','b']
643
668
  end
644
-
669
+
645
670
  it "should handle set intersections, unions, and diffs" do
646
671
  @set_1 << 'a' << 'b' << 'c' << 'd' << 'e'
647
672
  @set_2 << 'c' << 'd' << 'e' << 'f' << 'g'
@@ -716,14 +741,21 @@ describe Redis::Set do
716
741
  @set_2.sort(SORT_LIMIT).should == %w(3 4)
717
742
 
718
743
  @set_3 << 'm_4' << 'm_5' << 'm_1' << 'm_3' << 'm_2'
719
- @set_3.sort(:by => 'm_*').should == %w(m_1 m_2 m_3 m_4 m_5)
744
+ ### incorrect interpretation of what the :by parameter means
745
+ ### :by will look up values of keys so it would try to find a value in
746
+ ### redis of "m_m_1" which doesn't exist at this point, it is not a way to
747
+ ### alter the value to sort by but rather use a different value for this value
748
+ ### in the set (Kris Fox)
749
+ # @set_3.sort(:by => 'm_*').should == %w(m_1 m_2 m_3 m_4 m_5)
750
+ # below passes just fine
751
+ @set_3.sort.should == %w(m_1 m_2 m_3 m_4 m_5)
720
752
 
721
753
  val1 = Redis::Value.new('spec/3/sorted')
722
754
  val2 = Redis::Value.new('spec/4/sorted')
723
755
 
724
756
  val1.set('val3')
725
757
  val2.set('val4')
726
-
758
+
727
759
  @set_2.sort(SORT_GET).should == ['val3', 'val4']
728
760
  @set_2.sort(SORT_STORE).should == 2
729
761
  @set_2.redis.type(SORT_STORE[:store]).should == 'list'
@@ -740,7 +772,6 @@ describe Redis::Set do
740
772
  @set_1.clear
741
773
  @set_2.clear
742
774
  @set_3.clear
743
-
744
775
  end
745
776
  end
746
777
 
@@ -750,10 +781,12 @@ describe Redis::SortedSet do
750
781
  @set_1 = Redis::SortedSet.new('spec/zset_1')
751
782
  @set_2 = Redis::SortedSet.new('spec/zset_2')
752
783
  @set_3 = Redis::SortedSet.new('spec/zset_3')
784
+ @set_4 = Redis::SortedSet.new('spec/zset_3', :marshal => true)
753
785
  @set.clear
754
786
  @set_1.clear
755
787
  @set_2.clear
756
788
  @set_3.clear
789
+ @set_4.clear
757
790
  end
758
791
 
759
792
  it "should handle sorted sets of simple values" do
@@ -800,18 +833,17 @@ describe Redis::SortedSet do
800
833
  @set.should == ['a','b']
801
834
  @set.members.should == ['a','b']
802
835
  @set['d'] = 0
803
-
836
+
804
837
  @set.rangebyscore(0, 4).should == ['d','a']
805
838
  @set.rangebyscore(0, 4, :count => 1).should == ['d']
806
839
  @set.rangebyscore(0, 4, :count => 2).should == ['d','a']
807
840
  @set.rangebyscore(0, 4, :limit => 2).should == ['d','a']
808
841
 
809
- # Redis 1.3.5
810
- # @set.rangebyscore(0,4, :withscores => true).should == [['d',4],['a',3]]
811
- # @set.revrangebyscore(0,4).should == ['d','a']
812
- # @set.revrangebyscore(0,4, :count => 2).should == ['a','d']
813
- # @set.rank('b').should == 2
814
- # @set.revrank('b').should == 3
842
+ @set.revrangebyscore(4, 0, :withscores => true).should == [['a', 3], ['d', 0]]
843
+ @set.revrangebyscore(4, 0).should == ['a', 'd']
844
+ @set.revrangebyscore(4, 0, :count => 2).should == ['a','d']
845
+ @set.rank('b').should == 2
846
+ @set.revrank('b').should == 0
815
847
 
816
848
  # shouldn't report a rank for a key that doesn't exist
817
849
  @set.rank('foo').should.not == @set.rank(@set.first)
@@ -841,15 +873,24 @@ describe Redis::SortedSet do
841
873
  @set.delete('c')
842
874
  @set.length.should == 4
843
875
  @set.size.should == 4
844
-
876
+
845
877
  @set.range_size(100, 120).should == 0
846
878
  @set.range_size(0, 100).should == 2
847
879
  @set.range_size('-inf', 'inf').should == 4
848
-
880
+
849
881
  @set.delete_if{|m| m == 'b'}
850
882
  @set.size.should == 3
851
883
  end
852
884
 
885
+ it "should support marshaling key names" do
886
+ @set_4[Object] = 1.20
887
+ @set_4[Module] = 2.30
888
+ @set_4.incr(Object, 0.5)
889
+ @set_4.decr(Module, 0.5)
890
+ @set_4[Object].round(1).should == 1.7
891
+ @set_4[Module].round(1).should == 1.8
892
+ end
893
+
853
894
  it "should support renaming sorted sets" do
854
895
  @set.should.be.empty
855
896
  @set['zynga'] = 151
@@ -873,5 +914,6 @@ describe Redis::SortedSet do
873
914
  @set_1.clear
874
915
  @set_2.clear
875
916
  @set_3.clear
917
+ @set_4.clear
876
918
  end
877
919
  end