redis-objects 0.4.1 → 0.5.1
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.
- data/CHANGELOG.rdoc +24 -0
- data/README.rdoc +10 -9
- data/Rakefile +3 -2
- data/VERSION +1 -1
- data/lib/redis/base_object.rb +4 -2
- data/lib/redis/counter.rb +0 -1
- data/lib/redis/{hash.rb → hash_key.rb} +26 -10
- data/lib/redis/helpers/core_commands.rb +6 -8
- data/lib/redis/helpers/serialize.rb +7 -5
- data/lib/redis/list.rb +1 -1
- data/lib/redis/lock.rb +1 -1
- data/lib/redis/objects/counters.rb +18 -4
- data/lib/redis/objects/hashes.rb +3 -3
- data/lib/redis/objects.rb +27 -7
- data/lib/redis/sorted_set.rb +36 -20
- data/lib/redis/value.rb +0 -2
- data/redis-objects.gemspec +37 -43
- data/spec/redis_namespace_compat_spec.rb +24 -0
- data/spec/redis_objects_active_record_spec.rb +105 -0
- data/spec/redis_objects_instance_spec.rb +113 -6
- data/spec/redis_objects_model_spec.rb +52 -9
- data/spec/spec_helper.rb +11 -2
- metadata +13 -35
- data/.gitignore +0 -2
data/redis-objects.gemspec
CHANGED
|
@@ -1,76 +1,70 @@
|
|
|
1
1
|
# Generated by jeweler
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = %q{redis-objects}
|
|
8
|
-
s.version = "0.
|
|
8
|
+
s.version = "0.5.1"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Nate Wiger"]
|
|
12
|
-
s.date = %q{
|
|
12
|
+
s.date = %q{2011-05-23}
|
|
13
13
|
s.description = %q{Map Redis types directly to Ruby objects. Works with any class or ORM.}
|
|
14
14
|
s.email = %q{nate@wiger.org}
|
|
15
15
|
s.extra_rdoc_files = [
|
|
16
16
|
"README.rdoc"
|
|
17
17
|
]
|
|
18
18
|
s.files = [
|
|
19
|
-
".
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
19
|
+
"ATOMICITY.rdoc",
|
|
20
|
+
"CHANGELOG.rdoc",
|
|
21
|
+
"README.rdoc",
|
|
22
|
+
"Rakefile",
|
|
23
|
+
"VERSION",
|
|
24
|
+
"lib/redis/base_object.rb",
|
|
25
|
+
"lib/redis/counter.rb",
|
|
26
|
+
"lib/redis/hash_key.rb",
|
|
27
|
+
"lib/redis/helpers/core_commands.rb",
|
|
28
|
+
"lib/redis/helpers/serialize.rb",
|
|
29
|
+
"lib/redis/list.rb",
|
|
30
|
+
"lib/redis/lock.rb",
|
|
31
|
+
"lib/redis/objects.rb",
|
|
32
|
+
"lib/redis/objects/counters.rb",
|
|
33
|
+
"lib/redis/objects/hashes.rb",
|
|
34
|
+
"lib/redis/objects/lists.rb",
|
|
35
|
+
"lib/redis/objects/locks.rb",
|
|
36
|
+
"lib/redis/objects/sets.rb",
|
|
37
|
+
"lib/redis/objects/sorted_sets.rb",
|
|
38
|
+
"lib/redis/objects/values.rb",
|
|
39
|
+
"lib/redis/set.rb",
|
|
40
|
+
"lib/redis/sorted_set.rb",
|
|
41
|
+
"lib/redis/value.rb",
|
|
42
|
+
"redis-objects.gemspec",
|
|
43
|
+
"spec/redis_namespace_compat_spec.rb",
|
|
44
|
+
"spec/redis_objects_active_record_spec.rb",
|
|
45
|
+
"spec/redis_objects_instance_spec.rb",
|
|
46
|
+
"spec/redis_objects_model_spec.rb",
|
|
47
|
+
"spec/spec_helper.rb"
|
|
47
48
|
]
|
|
48
49
|
s.homepage = %q{http://github.com/nateware/redis-objects}
|
|
49
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
|
50
50
|
s.require_paths = ["lib"]
|
|
51
|
-
s.requirements = ["redis, v2.
|
|
52
|
-
s.rubygems_version = %q{1.
|
|
51
|
+
s.requirements = ["redis, v2.1.1 or greater"]
|
|
52
|
+
s.rubygems_version = %q{1.7.2}
|
|
53
53
|
s.summary = %q{Map Redis types directly to Ruby objects}
|
|
54
|
-
s.test_files = [
|
|
55
|
-
"spec/redis_objects_instance_spec.rb",
|
|
56
|
-
"spec/redis_objects_model_spec.rb",
|
|
57
|
-
"spec/spec_helper.rb"
|
|
58
|
-
]
|
|
59
54
|
|
|
60
55
|
if s.respond_to? :specification_version then
|
|
61
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
62
56
|
s.specification_version = 3
|
|
63
57
|
|
|
64
58
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
65
59
|
s.add_development_dependency(%q<bacon>, [">= 0"])
|
|
66
|
-
s.add_runtime_dependency(%q<redis>, [">= 2.
|
|
60
|
+
s.add_runtime_dependency(%q<redis>, [">= 2.1.1"])
|
|
67
61
|
else
|
|
68
62
|
s.add_dependency(%q<bacon>, [">= 0"])
|
|
69
|
-
s.add_dependency(%q<redis>, [">= 2.
|
|
63
|
+
s.add_dependency(%q<redis>, [">= 2.1.1"])
|
|
70
64
|
end
|
|
71
65
|
else
|
|
72
66
|
s.add_dependency(%q<bacon>, [">= 0"])
|
|
73
|
-
s.add_dependency(%q<redis>, [">= 2.
|
|
67
|
+
s.add_dependency(%q<redis>, [">= 2.1.1"])
|
|
74
68
|
end
|
|
75
69
|
end
|
|
76
70
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
require 'redis/objects'
|
|
4
|
+
Redis::Objects.redis = $redis
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../redis-namespace/lib')
|
|
7
|
+
begin
|
|
8
|
+
require 'redis/namespace'
|
|
9
|
+
|
|
10
|
+
describe 'Redis::Namespace compat' do
|
|
11
|
+
it "tests the compatibility of Hash and ::Hash conflicts" do
|
|
12
|
+
ns = Redis::Namespace.new("resque", :redis => $redis)
|
|
13
|
+
ns.instance_eval { rem_namespace({"resque:x" => nil}) }.should == {"x"=>nil}
|
|
14
|
+
class Foo
|
|
15
|
+
include Redis::Objects
|
|
16
|
+
end
|
|
17
|
+
ns.instance_eval { rem_namespace({"resque:x" => nil}) }.should == {"x"=>nil}
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
rescue LoadError
|
|
22
|
+
# Redis::Namespace not installed
|
|
23
|
+
puts "Skipping Redis::Namespace tests as redis-namespace is not installed"
|
|
24
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
3
|
+
|
|
4
|
+
require 'redis/objects'
|
|
5
|
+
Redis::Objects.redis = $redis
|
|
6
|
+
|
|
7
|
+
begin
|
|
8
|
+
require 'active_record'
|
|
9
|
+
ActiveRecord::Base.establish_connection(
|
|
10
|
+
:adapter => 'sqlite3',
|
|
11
|
+
:database => File.expand_path(File.dirname(__FILE__) + '/redis_objects_test.sqlite3')
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
class CreateBlogs < ActiveRecord::Migration
|
|
15
|
+
def self.up
|
|
16
|
+
create_table :blogs do |t|
|
|
17
|
+
t.string :name
|
|
18
|
+
t.integer :posts_count, :default => 0
|
|
19
|
+
t.timestamps
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.down
|
|
24
|
+
drop_table :blogs
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Blog < ActiveRecord::Base
|
|
29
|
+
include Redis::Objects
|
|
30
|
+
has_many :posts
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class CreatePosts < ActiveRecord::Migration
|
|
34
|
+
def self.up
|
|
35
|
+
create_table :posts do |t|
|
|
36
|
+
t.string :title
|
|
37
|
+
t.string :description, :length => 200
|
|
38
|
+
t.integer :total
|
|
39
|
+
t.integer :blog_id
|
|
40
|
+
t.timestamps
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.down
|
|
45
|
+
drop_table :posts
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class Post < ActiveRecord::Base
|
|
50
|
+
include Redis::Objects
|
|
51
|
+
counter :total
|
|
52
|
+
belongs_to :blog, :counter_cache => true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
describe Redis::Objects do
|
|
57
|
+
before do
|
|
58
|
+
CreatePosts.up
|
|
59
|
+
CreateBlogs.up
|
|
60
|
+
end
|
|
61
|
+
after do
|
|
62
|
+
CreatePosts.down
|
|
63
|
+
CreateBlogs.down
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "exercises ActiveRecord in more detail" do
|
|
67
|
+
@ar = Post.new
|
|
68
|
+
@ar.save!
|
|
69
|
+
@ar.destroy
|
|
70
|
+
|
|
71
|
+
# @ar.total.reset
|
|
72
|
+
@ar2 = Post.new
|
|
73
|
+
@ar2.save!
|
|
74
|
+
@ar2.total.reset
|
|
75
|
+
@ar2.total.increment.should == 1
|
|
76
|
+
@ar2.id.should == 2
|
|
77
|
+
@ar2.increment(:total).should == 2
|
|
78
|
+
@ar2[:total].should == nil # DB column
|
|
79
|
+
@ar2.redis.get(@ar2.redis_field_key('total')).to_i.should == 2
|
|
80
|
+
@ar2[:total] = 3 # DB column
|
|
81
|
+
@ar2.total.decrement.should == 1
|
|
82
|
+
@ar2.total.reset
|
|
83
|
+
@ar2.total.should == 0
|
|
84
|
+
@ar2.destroy
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "falls back to ActiveRecord if redis counter is not defined" do
|
|
88
|
+
blog = Blog.create
|
|
89
|
+
blog.reload.posts_count.should == 0
|
|
90
|
+
post = Post.create :blog => blog
|
|
91
|
+
blog.reload.posts_count.should == 1
|
|
92
|
+
blog2 = Blog.create
|
|
93
|
+
Post.create :blog => blog2
|
|
94
|
+
Post.create :blog => blog2
|
|
95
|
+
blog.reload.posts_count.should == 1
|
|
96
|
+
blog2.reload.posts_count.should == 2
|
|
97
|
+
blog.posts_count.should == 1
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
rescue LoadError
|
|
103
|
+
# ActiveRecord not install
|
|
104
|
+
puts "Skipping ActiveRecord tests as active_record is not installed"
|
|
105
|
+
end
|
|
@@ -7,7 +7,7 @@ require 'redis/value'
|
|
|
7
7
|
require 'redis/lock'
|
|
8
8
|
require 'redis/set'
|
|
9
9
|
require 'redis/sorted_set'
|
|
10
|
-
require 'redis/
|
|
10
|
+
require 'redis/hash_key'
|
|
11
11
|
|
|
12
12
|
describe Redis::Value do
|
|
13
13
|
before do
|
|
@@ -20,7 +20,7 @@ describe Redis::Value do
|
|
|
20
20
|
@value.value = 'Trevor Hoffman'
|
|
21
21
|
@value.should == 'Trevor Hoffman'
|
|
22
22
|
@value.get.should == 'Trevor Hoffman'
|
|
23
|
-
@value.del.should
|
|
23
|
+
@value.del.should == 1
|
|
24
24
|
@value.should.be.nil
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -40,7 +40,7 @@ describe Redis::Value do
|
|
|
40
40
|
@value.value = [[1,2], {:t3 => 4}]
|
|
41
41
|
@value.should == [[1,2], {:t3 => 4}]
|
|
42
42
|
@value.get.should == [[1,2], {:t3 => 4}]
|
|
43
|
-
@value.del.should
|
|
43
|
+
@value.del.should == 1
|
|
44
44
|
@value.should.be.nil
|
|
45
45
|
@value.options[:marshal] = false
|
|
46
46
|
end
|
|
@@ -197,6 +197,9 @@ describe Redis::List do
|
|
|
197
197
|
@list << [1,2,3,[4,5]]
|
|
198
198
|
@list.last.should == [1,2,3,[4,5]]
|
|
199
199
|
@list.shift.should == {:json => 'data'}
|
|
200
|
+
@list.size.should == 2
|
|
201
|
+
@list.delete(v2)
|
|
202
|
+
@list.size.should == 1
|
|
200
203
|
@list.options[:marshal] = false
|
|
201
204
|
end
|
|
202
205
|
|
|
@@ -356,12 +359,83 @@ describe Redis::Lock do
|
|
|
356
359
|
end
|
|
357
360
|
|
|
358
361
|
|
|
359
|
-
describe Redis::
|
|
362
|
+
describe Redis::HashKey do
|
|
363
|
+
describe "With Marshal" do
|
|
364
|
+
before do
|
|
365
|
+
@hash = Redis::HashKey.new('test_hash', $redis,
|
|
366
|
+
{:marshal_keys=>{'created_at'=>true}})
|
|
367
|
+
@hash.clear
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it "should marshal specified keys" do
|
|
371
|
+
@hash['created_at'] = Time.now
|
|
372
|
+
@hash['created_at'].class.should == Time
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it "should not marshal unless required" do
|
|
376
|
+
@hash['updated_at'] = Time.now
|
|
377
|
+
@hash['updated_at'].class.should == String
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
it "should marshall appropriate key with bulk set and get" do
|
|
381
|
+
@hash.bulk_set({'created_at'=>Time.now, 'updated_at'=>Time.now})
|
|
382
|
+
|
|
383
|
+
@hash['created_at'].class.should == Time
|
|
384
|
+
@hash['updated_at'].class.should == String
|
|
385
|
+
|
|
386
|
+
h = @hash.bulk_get('created_at', 'updated_at')
|
|
387
|
+
h['created_at'].class.should == Time
|
|
388
|
+
h['updated_at'].class.should == String
|
|
389
|
+
|
|
390
|
+
h = @hash.all
|
|
391
|
+
h['created_at'].class.should == Time
|
|
392
|
+
h['updated_at'].class.should == String
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
360
396
|
before do
|
|
361
|
-
@hash = Redis::
|
|
397
|
+
@hash = Redis::HashKey.new('test_hash')
|
|
362
398
|
@hash.clear
|
|
363
399
|
end
|
|
364
400
|
|
|
401
|
+
it "should handle complex marshaled values" do
|
|
402
|
+
@hash.options[:marshal] = true
|
|
403
|
+
@hash['abc'].should == nil
|
|
404
|
+
@hash['abc'] = {:json => 'data'}
|
|
405
|
+
@hash['abc'].should == {:json => 'data'}
|
|
406
|
+
|
|
407
|
+
# no marshaling
|
|
408
|
+
@hash.options[:marshal] = false
|
|
409
|
+
v = {:json => 'data'}
|
|
410
|
+
@hash['abc'] = v
|
|
411
|
+
@hash['abc'].should == v.to_s
|
|
412
|
+
|
|
413
|
+
@hash.options[:marshal] = true
|
|
414
|
+
@hash['abc'] = [[1,2], {:t3 => 4}]
|
|
415
|
+
@hash['abc'].should == [[1,2], {:t3 => 4}]
|
|
416
|
+
@hash.fetch('abc').should == [[1,2], {:t3 => 4}]
|
|
417
|
+
@hash.delete('abc').should == 1
|
|
418
|
+
@hash.fetch('abc').should.be.nil
|
|
419
|
+
|
|
420
|
+
@hash.options[:marshal] = true
|
|
421
|
+
@hash.bulk_set('abc' => [[1,2], {:t3 => 4}], 'def' => [[6,8], {:t4 => 8}])
|
|
422
|
+
hsh = @hash.bulk_get('abc', 'def', 'foo')
|
|
423
|
+
hsh['abc'].should == [[1,2], {:t3 => 4}]
|
|
424
|
+
hsh['def'].should == [[6,8], {:t4 => 8}]
|
|
425
|
+
hsh['foo'].should.be.nil
|
|
426
|
+
|
|
427
|
+
hsh = @hash.all
|
|
428
|
+
hsh['abc'].should == [[1,2], {:t3 => 4}]
|
|
429
|
+
hsh['def'].should == [[6,8], {:t4 => 8}]
|
|
430
|
+
|
|
431
|
+
@hash.values.should == [[[1,2], {:t3 => 4}], [[6,8], {:t4 => 8}]]
|
|
432
|
+
|
|
433
|
+
@hash.delete('def').should == 1
|
|
434
|
+
@hash.delete('abc').should == 1
|
|
435
|
+
|
|
436
|
+
@hash.options[:marshal] = false
|
|
437
|
+
end
|
|
438
|
+
|
|
365
439
|
it "should get and set values" do
|
|
366
440
|
@hash['foo'] = 'bar'
|
|
367
441
|
@hash['foo'].should == 'bar'
|
|
@@ -406,7 +480,7 @@ describe Redis::Hash do
|
|
|
406
480
|
end
|
|
407
481
|
|
|
408
482
|
it "should respond to empty?" do
|
|
409
|
-
@empty = Redis::
|
|
483
|
+
@empty = Redis::HashKey.new('test_empty_hash')
|
|
410
484
|
@empty.respond_to?(:empty?).should == true
|
|
411
485
|
end
|
|
412
486
|
|
|
@@ -560,11 +634,40 @@ describe Redis::Set do
|
|
|
560
634
|
@set.redis.del('spec/set2')
|
|
561
635
|
end
|
|
562
636
|
|
|
637
|
+
it "should support sorting" do
|
|
638
|
+
@set_1 << 'a' << 'b' << 'c' << 'd' << 'e'
|
|
639
|
+
@set_2 << 1 << 2 << 3 << 4 << 5
|
|
640
|
+
@set_3 << 'm_1' << 'm_2'
|
|
641
|
+
@set_1.sort.should == %w(a b c d e)
|
|
642
|
+
@set_2.sort.should == %w(1 2 3 4 5)
|
|
643
|
+
|
|
644
|
+
@set_1.sort(SORT_ORDER).should == %w(e d c b a)
|
|
645
|
+
@set_3.sort(SORT_BY).should == %w(m_1 m_2)
|
|
646
|
+
@set_2.sort(SORT_LIMIT).should == %w(3 4)
|
|
647
|
+
|
|
648
|
+
val1 = Redis::Value.new('spec/3/sorted')
|
|
649
|
+
val2 = Redis::Value.new('spec/4/sorted')
|
|
650
|
+
|
|
651
|
+
val1.set('val3')
|
|
652
|
+
val2.set('val4')
|
|
653
|
+
|
|
654
|
+
@set_2.sort(SORT_GET).should == ['val3', 'val4']
|
|
655
|
+
@set_2.sort(SORT_STORE).should == 2
|
|
656
|
+
@set_2.redis.type(SORT_STORE[:store]).should == 'list'
|
|
657
|
+
@set_2.redis.lrange(SORT_STORE[:store], 0, -1).should == ['val3', 'val4']
|
|
658
|
+
|
|
659
|
+
@set_1.redis.del val1.key
|
|
660
|
+
@set_1.redis.del val2.key
|
|
661
|
+
@set_1.redis.del SORT_STORE[:store]
|
|
662
|
+
|
|
663
|
+
end
|
|
664
|
+
|
|
563
665
|
after do
|
|
564
666
|
@set.clear
|
|
565
667
|
@set_1.clear
|
|
566
668
|
@set_2.clear
|
|
567
669
|
@set_3.clear
|
|
670
|
+
|
|
568
671
|
end
|
|
569
672
|
end
|
|
570
673
|
|
|
@@ -657,6 +760,10 @@ describe Redis::SortedSet do
|
|
|
657
760
|
@set.length.should == 4
|
|
658
761
|
@set.size.should == 4
|
|
659
762
|
|
|
763
|
+
@set.range_size(100, 120).should == 0
|
|
764
|
+
@set.range_size(0, 100).should == 2
|
|
765
|
+
@set.range_size('-inf', 'inf').should == 4
|
|
766
|
+
|
|
660
767
|
@set.delete_if{|m| m == 'b'}
|
|
661
768
|
@set.size.should == 3
|
|
662
769
|
end
|
|
@@ -9,7 +9,7 @@ class Roster
|
|
|
9
9
|
counter :available_slots, :start => 10
|
|
10
10
|
counter :pitchers, :limit => :max_pitchers
|
|
11
11
|
counter :basic
|
|
12
|
-
hash_key :contact_information
|
|
12
|
+
hash_key :contact_information, :marshal_keys=>{'updated_at'=>true}
|
|
13
13
|
lock :resort, :timeout => 2
|
|
14
14
|
value :starting_pitcher, :marshal => true
|
|
15
15
|
list :player_stats, :marshal => true
|
|
@@ -18,17 +18,19 @@ class Roster
|
|
|
18
18
|
|
|
19
19
|
# global class counters
|
|
20
20
|
counter :total_players_online, :global => true
|
|
21
|
-
list :all_player_stats, :global => true
|
|
22
21
|
set :all_players_online, :global => true
|
|
23
22
|
value :last_player, :global => true
|
|
24
23
|
|
|
25
24
|
# custom keys
|
|
26
25
|
counter :player_totals, :key => 'players/#{username}/total'
|
|
27
|
-
list :all_player_stats, :key => 'players:all_stats'
|
|
26
|
+
list :all_player_stats, :key => 'players:all_stats', :global => true
|
|
28
27
|
set :total_wins, :key => 'players:#{id}:all_stats'
|
|
29
28
|
value :my_rank, :key => 'players:my_rank:#{username}'
|
|
30
29
|
value :weird_key, :key => 'players:weird_key:#{raise}', :global => true
|
|
31
30
|
|
|
31
|
+
#callable as key
|
|
32
|
+
counter :daily, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" }
|
|
33
|
+
|
|
32
34
|
def initialize(id=1) @id = id end
|
|
33
35
|
def id; @id; end
|
|
34
36
|
def username; "user#{id}"; end
|
|
@@ -46,6 +48,21 @@ class CustomRoster < Roster
|
|
|
46
48
|
counter :special # New
|
|
47
49
|
end
|
|
48
50
|
|
|
51
|
+
class MethodRoster
|
|
52
|
+
def increment(attribute, by=1)
|
|
53
|
+
42
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def initialize(id=1) @id = id end
|
|
57
|
+
def id; @id; end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class CustomMethodRoster < MethodRoster
|
|
61
|
+
include Redis::Objects
|
|
62
|
+
|
|
63
|
+
attr_accessor :counter
|
|
64
|
+
counter :basic
|
|
65
|
+
end
|
|
49
66
|
|
|
50
67
|
describe Redis::Objects do
|
|
51
68
|
before do
|
|
@@ -85,6 +102,8 @@ describe Redis::Objects do
|
|
|
85
102
|
@roster.total_wins.clear
|
|
86
103
|
@roster.my_rank.clear
|
|
87
104
|
|
|
105
|
+
@roster.daily.clear
|
|
106
|
+
|
|
88
107
|
@custom_roster.basic.reset
|
|
89
108
|
@custom_roster.special.reset
|
|
90
109
|
end
|
|
@@ -93,7 +112,7 @@ describe Redis::Objects do
|
|
|
93
112
|
Roster.redis.should == Redis::Objects.redis
|
|
94
113
|
# Roster.redis.should.be.kind_of(Redis)
|
|
95
114
|
end
|
|
96
|
-
|
|
115
|
+
|
|
97
116
|
it "should support interpolation of key names" do
|
|
98
117
|
@roster.player_totals.incr
|
|
99
118
|
@roster.redis.get('players/user1/total').should == '1'
|
|
@@ -108,6 +127,10 @@ describe Redis::Objects do
|
|
|
108
127
|
@roster.redis.get('players:my_rank:user1').should == 'a'
|
|
109
128
|
Roster.weird_key = 'tuka'
|
|
110
129
|
Roster.redis.get('players:weird_key:#{raise}').should == 'tuka'
|
|
130
|
+
|
|
131
|
+
k = "Roster:#{Time.now.strftime('%Y-%m-%dT%H')}:daily"
|
|
132
|
+
@roster.daily.incr
|
|
133
|
+
@roster.redis.get(k).should == '1'
|
|
111
134
|
end
|
|
112
135
|
|
|
113
136
|
it "should be able to get/set contact info" do
|
|
@@ -119,6 +142,10 @@ describe Redis::Objects do
|
|
|
119
142
|
@roster.contact_information.size.should == 2
|
|
120
143
|
end
|
|
121
144
|
|
|
145
|
+
it "should be marshalling hash keys" do
|
|
146
|
+
@roster.contact_information['updated_at'] = Time.now
|
|
147
|
+
@roster.contact_information['updated_at'].class.should == Time
|
|
148
|
+
end
|
|
122
149
|
|
|
123
150
|
|
|
124
151
|
it "should create counter accessors" do
|
|
@@ -312,7 +339,7 @@ describe Redis::Objects do
|
|
|
312
339
|
Roster.increment_counter(:badness, 2)
|
|
313
340
|
rescue => error
|
|
314
341
|
end
|
|
315
|
-
error.should.be.kind_of(
|
|
342
|
+
error.should.be.kind_of(NoMethodError)
|
|
316
343
|
|
|
317
344
|
error = nil
|
|
318
345
|
begin
|
|
@@ -363,7 +390,7 @@ describe Redis::Objects do
|
|
|
363
390
|
@roster.starting_pitcher.get.should == 'Trevor Hoffman'
|
|
364
391
|
@roster.starting_pitcher = 'Tom Selleck'
|
|
365
392
|
@roster.starting_pitcher.should == 'Tom Selleck'
|
|
366
|
-
@roster.starting_pitcher.del.should
|
|
393
|
+
@roster.starting_pitcher.del.should == 1
|
|
367
394
|
@roster.starting_pitcher.should.be.nil
|
|
368
395
|
end
|
|
369
396
|
|
|
@@ -372,7 +399,7 @@ describe Redis::Objects do
|
|
|
372
399
|
@roster.starting_pitcher = {:json => 'data'}
|
|
373
400
|
@roster.starting_pitcher.should == {:json => 'data'}
|
|
374
401
|
@roster.starting_pitcher.get.should == {:json => 'data'}
|
|
375
|
-
@roster.starting_pitcher.del.should
|
|
402
|
+
@roster.starting_pitcher.del.should == 1
|
|
376
403
|
@roster.starting_pitcher.should.be.nil
|
|
377
404
|
end
|
|
378
405
|
|
|
@@ -630,7 +657,7 @@ describe Redis::Objects do
|
|
|
630
657
|
Roster.last_player.get.should == 'Trevor Hoffman'
|
|
631
658
|
Roster.last_player = 'Tom Selleck'
|
|
632
659
|
Roster.last_player.should == 'Tom Selleck'
|
|
633
|
-
Roster.last_player.del.should
|
|
660
|
+
Roster.last_player.del.should == 1
|
|
634
661
|
Roster.last_player.should.be.nil
|
|
635
662
|
end
|
|
636
663
|
|
|
@@ -664,7 +691,7 @@ describe Redis::Objects do
|
|
|
664
691
|
@roster2.last_player.get.should == 'Trevor Hoffman'
|
|
665
692
|
@roster2.last_player = 'Tom Selleck'
|
|
666
693
|
@roster.last_player.should == 'Tom Selleck'
|
|
667
|
-
@roster.last_player.del.should
|
|
694
|
+
@roster.last_player.del.should == 1
|
|
668
695
|
@roster.last_player.should.be.nil
|
|
669
696
|
@roster2.last_player.should.be.nil
|
|
670
697
|
end
|
|
@@ -743,9 +770,25 @@ describe Redis::Objects do
|
|
|
743
770
|
@custom_roster.basic.increment.should == 1
|
|
744
771
|
@roster2.basic.should == 0
|
|
745
772
|
CustomRoster.new.basic.should == 1
|
|
773
|
+
@custom_roster.basic.decrement.should == 0
|
|
746
774
|
end
|
|
747
775
|
|
|
748
776
|
it "should handle new subclass objects" do
|
|
749
777
|
@custom_roster.special.increment.should == 1
|
|
750
778
|
end
|
|
779
|
+
|
|
780
|
+
it "should allow passing of increment/decrement to super class" do
|
|
781
|
+
@custom_method_roster = CustomMethodRoster.new
|
|
782
|
+
@custom_method_roster.counter.should.be.nil
|
|
783
|
+
|
|
784
|
+
@custom_method_roster.increment(:counter).should == 42
|
|
785
|
+
|
|
786
|
+
@custom_method_roster.increment(:basic).should == 1
|
|
787
|
+
@custom_method_roster.basic.increment.should == 2
|
|
788
|
+
@custom_method_roster.decrement(:basic).should == 1
|
|
789
|
+
@custom_method_roster.basic.decrement.should == 0
|
|
790
|
+
@custom_method_roster.basic.reset.should.be.true
|
|
791
|
+
@custom_method_roster.basic.should == 0
|
|
792
|
+
@custom_method_roster.basic.should.be.kind_of(Redis::Counter)
|
|
793
|
+
end
|
|
751
794
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
require 'rubygems' # poor people still on 1.8
|
|
2
|
-
|
|
3
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
|
2
|
+
gem 'redis', '>= 2.1.1'
|
|
4
3
|
require 'redis'
|
|
5
4
|
|
|
5
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
|
6
6
|
require 'bacon'
|
|
7
7
|
Bacon.summary_at_exit
|
|
8
8
|
|
|
@@ -11,3 +11,12 @@ $redis = Redis.new(:host => ENV['REDIS_HOST'], :port => ENV['REDIS_PORT'])
|
|
|
11
11
|
UNIONSTORE_KEY = 'test:unionstore'
|
|
12
12
|
INTERSTORE_KEY = 'test:interstore'
|
|
13
13
|
DIFFSTORE_KEY = 'test:diffstore'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
SORT_ORDER = {:order => 'desc alpha'}
|
|
17
|
+
SORT_LIMIT = {:limit => [2, 2]}
|
|
18
|
+
SORT_BY = {:by => 'm_*'}
|
|
19
|
+
SORT_GET = {:get => 'spec/*/sorted'}.merge!(SORT_LIMIT)
|
|
20
|
+
SORT_STORE = {:store => "spec/aftersort"}.merge!(SORT_GET)
|
|
21
|
+
|
|
22
|
+
|