nest 0.0.7 → 1.0.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.
- data/README.markdown +47 -33
- data/Rakefile +2 -1
- data/lib/nest.rb +6 -8
- data/nest.gemspec +4 -2
- data/test/nest_test.rb +62 -67
- data/test/test_helper.rb +1 -1
- metadata +34 -6
data/README.markdown
CHANGED
@@ -1,32 +1,31 @@
|
|
1
1
|
Nest
|
2
2
|
====
|
3
3
|
|
4
|
-
|
4
|
+
Object Oriented Keys for Redis.
|
5
5
|
|
6
6
|
Description
|
7
7
|
-----------
|
8
8
|
|
9
|
-
If you are familiar with databases like
|
10
|
-
[
|
11
|
-
|
12
|
-
[redis-namespace](http://github.com/defunkt/redis-namespace), you
|
13
|
-
already know how important it is to craft the keys that will hold the
|
14
|
-
data.
|
9
|
+
If you are familiar with databases like [Redis](http://code.google.com/p/redis)
|
10
|
+
and libraries like [Ohm](http://ohm.keyvalue.org) you already know how
|
11
|
+
important it is to craft the keys that will hold the data.
|
15
12
|
|
16
|
-
>>
|
17
|
-
>>
|
18
|
-
|
13
|
+
>> redis = Redis.new
|
14
|
+
>> redis.sadd("event:3:attendees", "Albert")
|
15
|
+
>> redis.smembers("event:3:attendees")
|
16
|
+
=> ["Albert"]
|
19
17
|
|
20
18
|
It is a design pattern in key-value databases to use the key to simulate
|
21
19
|
structure, and you can read more about this in the [case study for a
|
22
20
|
Twitter clone](http://code.google.com/p/redis/wiki/TwitterAlikeExample).
|
23
21
|
|
24
|
-
Nest helps you generate those keys by providing chainable namespaces
|
22
|
+
Nest helps you generate those keys by providing chainable namespaces that are
|
23
|
+
already connected to Redis:
|
25
24
|
|
26
25
|
>> event = Nest.new("event")
|
27
|
-
>>
|
28
|
-
>>
|
29
|
-
=> "
|
26
|
+
>> event[3][:attendees].sadd("Albert")
|
27
|
+
>> event[3][:attendees].smembers
|
28
|
+
=> ["Albert"]
|
30
29
|
|
31
30
|
Usage
|
32
31
|
-----
|
@@ -53,34 +52,41 @@ dealing with events:
|
|
53
52
|
>> events = Nest.new("events")
|
54
53
|
=> "events"
|
55
54
|
|
56
|
-
>>
|
57
|
-
=> #<Redis::Client...>
|
58
|
-
|
59
|
-
>> id = redis.incr(event)
|
55
|
+
>> id = events[:id].incr
|
60
56
|
=> 1
|
61
57
|
|
62
|
-
>>
|
58
|
+
>> events[id][:attendees].sadd("Albert")
|
63
59
|
=> "OK"
|
64
60
|
|
65
|
-
>> redis.get events[id][:name]
|
66
|
-
=> "Redis Meetup"
|
67
|
-
|
68
61
|
>> meetup = events[id]
|
69
62
|
=> "events:1"
|
70
63
|
|
71
|
-
>>
|
72
|
-
=> "
|
64
|
+
>> meetup[:attendees].smembers
|
65
|
+
=> ["Albert"]
|
73
66
|
|
74
|
-
|
75
|
-
|
67
|
+
Supplying your existing Redis instance
|
68
|
+
--------------------------------------
|
76
69
|
|
77
|
-
|
78
|
-
|
70
|
+
You can supply a `Redis` instance as a second parameter. If you don't, a default
|
71
|
+
instance is created for you:
|
79
72
|
|
80
73
|
>> redis = Redis.new
|
81
74
|
=> #<Redis::Client...>
|
82
75
|
|
83
|
-
>>
|
76
|
+
>> users = Nest.new("users", redis)
|
77
|
+
=> "users"
|
78
|
+
|
79
|
+
>> id = users[:id].incr
|
80
|
+
=> 1
|
81
|
+
|
82
|
+
>> users[id].hset(:name, "Albert")
|
83
|
+
=> "OK"
|
84
|
+
|
85
|
+
`Nest` objects respond to `redis` and return a `Redis` instance. It is
|
86
|
+
automatically reused when you create a new namespace, and you can reuse it when
|
87
|
+
creating a new instance of Nest:
|
88
|
+
|
89
|
+
>> events = Nest.new("events", meetup.redis)
|
84
90
|
=> "events"
|
85
91
|
|
86
92
|
>> events.sadd(meetup)
|
@@ -95,8 +101,9 @@ Redis directly:
|
|
95
101
|
>> events.del
|
96
102
|
>> true
|
97
103
|
|
98
|
-
|
99
|
-
first parameter. Think of it as a
|
104
|
+
Nest allows you to execute all the Redis commands that expect a key as the
|
105
|
+
first parameter. Think of it as a
|
106
|
+
[curried](http://en.wikipedia.org/wiki/Currying) Redis client.
|
100
107
|
|
101
108
|
Differences with redis-namespace
|
102
109
|
--------------------------------
|
@@ -109,6 +116,10 @@ different scope.
|
|
109
116
|
|
110
117
|
Use Nest when you want to use the keys to represent structure.
|
111
118
|
|
119
|
+
Tip: instead of using redis-namespace, it is recommended that you run a
|
120
|
+
different instance of `redis-server`. Translating keys back and forth is not
|
121
|
+
only delicate, but unnecessary and counterproductive.
|
122
|
+
|
112
123
|
Differences with Ohm
|
113
124
|
--------------------
|
114
125
|
|
@@ -119,12 +130,15 @@ between objects.
|
|
119
130
|
|
120
131
|
Use Ohm when you want to use Redis as your database.
|
121
132
|
|
122
|
-
Use Nest when mapping objects with Ohm is not possible.
|
133
|
+
Use Nest when mapping objects with Ohm is not possible or overkill.
|
134
|
+
|
135
|
+
Tip: Ohm uses Nest internally to deal with keys. Having a good knowledge
|
136
|
+
of Nest will let you extend Ohm to suit your needs.
|
123
137
|
|
124
138
|
Installation
|
125
139
|
------------
|
126
140
|
|
127
|
-
$
|
141
|
+
$ gem install nest
|
128
142
|
|
129
143
|
License
|
130
144
|
-------
|
data/Rakefile
CHANGED
data/lib/nest.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
require "redis"
|
2
|
+
|
1
3
|
class Nest < String
|
2
|
-
VERSION = "0.0
|
4
|
+
VERSION = "1.0.0"
|
3
5
|
|
4
6
|
METHODS = [:append, :blpop, :brpop, :decr, :decrby, :del, :exists,
|
5
7
|
:expire, :expireat, :get, :getset, :hdel, :hexists, :hget, :hgetall,
|
@@ -15,7 +17,9 @@ class Nest < String
|
|
15
17
|
:zrem, :zremrangebyrank, :zremrangebyscore, :zrevrange, :zrevrank,
|
16
18
|
:zscore, :zunionstore]
|
17
19
|
|
18
|
-
|
20
|
+
attr :redis
|
21
|
+
|
22
|
+
def initialize(key, redis = Redis.connect)
|
19
23
|
super(key.to_s)
|
20
24
|
@redis = redis
|
21
25
|
end
|
@@ -29,10 +33,4 @@ class Nest < String
|
|
29
33
|
redis.send(meth, self, *args, &block)
|
30
34
|
end
|
31
35
|
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def redis
|
36
|
-
@redis
|
37
|
-
end
|
38
36
|
end
|
data/nest.gemspec
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "nest"
|
3
|
-
s.version = "0.0
|
4
|
-
s.summary = "
|
3
|
+
s.version = "1.0.0"
|
4
|
+
s.summary = "Object Oriented Keys for Redis."
|
5
5
|
s.description = "It is a design pattern in key-value databases to use the key to simulate structure, and Nest can take care of that."
|
6
6
|
s.authors = ["Michel Martens"]
|
7
7
|
s.email = ["michel@soveran.com"]
|
8
8
|
s.homepage = "http://github.com/soveran/nest"
|
9
9
|
s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/nest.rb", "nest.gemspec", "test/nest_test.rb", "test/test_helper.rb"]
|
10
|
+
s.add_dependency "redis", "~> 2.0.0"
|
11
|
+
s.add_development_dependency "cutest", "~> 0.1"
|
10
12
|
end
|
data/test/nest_test.rb
CHANGED
@@ -1,91 +1,86 @@
|
|
1
1
|
require File.expand_path("test_helper", File.dirname(__FILE__))
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
should "prepend the namespace" do
|
11
|
-
n1 = Nest.new("foo")
|
12
|
-
assert_equal "foo:bar", n1["bar"]
|
13
|
-
end
|
14
|
-
|
15
|
-
should "work in more than one level" do
|
16
|
-
n1 = Nest.new("foo")
|
17
|
-
n2 = Nest.new(n1["bar"])
|
18
|
-
assert_equal "foo:bar:baz", n2["baz"]
|
19
|
-
end
|
3
|
+
# Creating namespaces.
|
4
|
+
scope do
|
5
|
+
test "return the namespace" do
|
6
|
+
n1 = Nest.new("foo")
|
7
|
+
assert "foo" == n1
|
8
|
+
end
|
20
9
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
10
|
+
test "prepend the namespace" do
|
11
|
+
n1 = Nest.new("foo")
|
12
|
+
assert "foo:bar" == n1["bar"]
|
13
|
+
end
|
25
14
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
15
|
+
test "work in more than one level" do
|
16
|
+
n1 = Nest.new("foo")
|
17
|
+
n2 = Nest.new(n1["bar"])
|
18
|
+
assert "foo:bar:baz" == n2["baz"]
|
19
|
+
end
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
21
|
+
test "be chainable" do
|
22
|
+
n1 = Nest.new("foo")
|
23
|
+
assert "foo:bar:baz" == n1["bar"]["baz"]
|
35
24
|
end
|
36
25
|
|
37
|
-
|
38
|
-
|
26
|
+
test "accept symbols" do
|
27
|
+
n1 = Nest.new(:foo)
|
28
|
+
assert "foo:bar" == n1[:bar]
|
29
|
+
end
|
39
30
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
test "accept numbers" do
|
32
|
+
n1 = Nest.new("foo")
|
33
|
+
assert "foo:3" == n1[3]
|
34
|
+
end
|
35
|
+
end
|
44
36
|
|
45
|
-
|
46
|
-
|
37
|
+
# Operating with redis.
|
38
|
+
scope do
|
39
|
+
prepare do
|
40
|
+
@redis = Redis.new
|
41
|
+
@redis.flushdb
|
42
|
+
end
|
47
43
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
44
|
+
test "work if no redis instance was passed" do
|
45
|
+
n1 = Nest.new("foo")
|
46
|
+
n1.set("s1")
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
n1.set("s1")
|
48
|
+
assert "s1" == n1.get
|
49
|
+
end
|
56
50
|
|
57
|
-
|
58
|
-
|
51
|
+
test "work if a redis instance is supplied" do
|
52
|
+
n1 = Nest.new("foo", @redis)
|
53
|
+
n1.set("s1")
|
59
54
|
|
60
|
-
|
61
|
-
|
62
|
-
n1["bar"].set("s2")
|
55
|
+
assert "s1" == n1.get
|
56
|
+
end
|
63
57
|
|
64
|
-
|
65
|
-
|
66
|
-
end
|
58
|
+
test "pass the redis instance to new keys" do
|
59
|
+
n1 = Nest.new("foo", @redis)
|
67
60
|
|
68
|
-
|
69
|
-
|
70
|
-
listening = false
|
71
|
-
message_received = false
|
61
|
+
assert @redis.id == n1["bar"].redis.id
|
62
|
+
end
|
72
63
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
64
|
+
test "PubSub" do
|
65
|
+
foo = Nest.new("foo", @redis)
|
66
|
+
listening = false
|
67
|
+
message_received = false
|
77
68
|
|
78
|
-
|
79
|
-
|
80
|
-
|
69
|
+
Thread.new do
|
70
|
+
while !listening; end
|
71
|
+
Nest.new("foo", Redis.new(:db => 15)).publish("")
|
72
|
+
end
|
81
73
|
|
82
|
-
|
83
|
-
|
74
|
+
foo.subscribe do |on|
|
75
|
+
on.message do
|
76
|
+
message_received = true
|
84
77
|
|
85
|
-
|
78
|
+
foo.unsubscribe
|
86
79
|
end
|
87
80
|
|
88
|
-
|
81
|
+
listening = true
|
89
82
|
end
|
83
|
+
|
84
|
+
assert message_received
|
90
85
|
end
|
91
86
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -3,10 +3,10 @@ name: nest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
+
- 1
|
6
7
|
- 0
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.7
|
9
|
+
version: 1.0.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Michel Martens
|
@@ -14,10 +14,38 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-10-22 00:00:00 -03:00
|
18
18
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: redis
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
version: 2.0.0
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: cutest
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 1
|
46
|
+
version: "0.1"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
21
49
|
description: It is a design pattern in key-value databases to use the key to simulate structure, and Nest can take care of that.
|
22
50
|
email:
|
23
51
|
- michel@soveran.com
|
@@ -66,6 +94,6 @@ rubyforge_project:
|
|
66
94
|
rubygems_version: 1.3.7
|
67
95
|
signing_key:
|
68
96
|
specification_version: 3
|
69
|
-
summary:
|
97
|
+
summary: Object Oriented Keys for Redis.
|
70
98
|
test_files: []
|
71
99
|
|