nest 0.0.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,32 +1,31 @@
1
1
  Nest
2
2
  ====
3
3
 
4
- Generate nested namespaced keys for key-value databases.
4
+ Object Oriented Keys for Redis.
5
5
 
6
6
  Description
7
7
  -----------
8
8
 
9
- If you are familiar with databases like
10
- [Redis](http://code.google.com/p/redis) and
11
- libraries like [Ohm](http://ohm.keyvalue.org) or
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
- >> @redis.set "event:3:name", "Redis Meetup"
17
- >> @redis.get "event:3:name"
18
- => "Redis Meetup"
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
- >> @redis.set event[3][:name], "Redis Meetup"
28
- >> @redis.get event[3][:name]
29
- => "Redis Meetup"
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
- >> redis = Redis.new
57
- => #<Redis::Client...>
58
-
59
- >> id = redis.incr(event)
55
+ >> id = events[:id].incr
60
56
  => 1
61
57
 
62
- >> redis.set events[id][:name], "Redis Meetup"
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
- >> redis.get meetup[:name]
72
- => "Redis Meetup"
64
+ >> meetup[:attendees].smembers
65
+ => ["Albert"]
73
66
 
74
- Using Nest as an object oriented Redis key
75
- ------------------------------------------
67
+ Supplying your existing Redis instance
68
+ --------------------------------------
76
69
 
77
- If you supply a Redis client as a second parameter, you can operate with
78
- Redis directly:
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
- >> events = Nest.new("events", redis)
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
- It allows you to execute all the Redis commands that expect a key as the
99
- first parameter. Think of it as a curried Redis client.
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
- $ sudo gem install nest
141
+ $ gem install nest
128
142
 
129
143
  License
130
144
  -------
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  task :test do
2
- system "cd test && ruby nest_test.rb"
2
+ require "cutest"
3
+ Cutest.run(Dir["test/nest*"])
3
4
  end
4
5
 
5
6
  task :default => :test
@@ -1,5 +1,7 @@
1
+ require "redis"
2
+
1
3
  class Nest < String
2
- VERSION = "0.0.7"
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
- def initialize(key, redis = nil)
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
@@ -1,10 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "nest"
3
- s.version = "0.0.7"
4
- s.summary = "Generate nested namespaced keys for key-value databases."
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
@@ -1,91 +1,86 @@
1
1
  require File.expand_path("test_helper", File.dirname(__FILE__))
2
2
 
3
- class TestNest < Test::Unit::TestCase
4
- context "creating namespaces" do
5
- should "return the namespace" do
6
- n1 = Nest.new("foo")
7
- assert_equal "foo", n1
8
- end
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
- should "be chainable" do
22
- n1 = Nest.new("foo")
23
- assert_equal "foo:bar:baz", n1["bar"]["baz"]
24
- end
10
+ test "prepend the namespace" do
11
+ n1 = Nest.new("foo")
12
+ assert "foo:bar" == n1["bar"]
13
+ end
25
14
 
26
- should "accept symbols" do
27
- n1 = Nest.new(:foo)
28
- assert_equal "foo:bar", n1[:bar]
29
- end
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
- should "accept numbers" do
32
- n1 = Nest.new("foo")
33
- assert_equal "foo:3", n1[3]
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
- context "operating with redis" do
38
- require "redis"
26
+ test "accept symbols" do
27
+ n1 = Nest.new(:foo)
28
+ assert "foo:bar" == n1[:bar]
29
+ end
39
30
 
40
- setup do
41
- @redis = Redis.new :db => 15
42
- @redis.flushdb
43
- end
31
+ test "accept numbers" do
32
+ n1 = Nest.new("foo")
33
+ assert "foo:3" == n1[3]
34
+ end
35
+ end
44
36
 
45
- should "raise if no redis instance was passed" do
46
- n1 = Nest.new("foo")
37
+ # Operating with redis.
38
+ scope do
39
+ prepare do
40
+ @redis = Redis.new
41
+ @redis.flushdb
42
+ end
47
43
 
48
- assert_raises NoMethodError do
49
- n1.set("s1")
50
- end
51
- end
44
+ test "work if no redis instance was passed" do
45
+ n1 = Nest.new("foo")
46
+ n1.set("s1")
52
47
 
53
- should "work if a redis instance is supplied" do
54
- n1 = Nest.new("foo", @redis)
55
- n1.set("s1")
48
+ assert "s1" == n1.get
49
+ end
56
50
 
57
- assert_equal "s1", n1.get
58
- end
51
+ test "work if a redis instance is supplied" do
52
+ n1 = Nest.new("foo", @redis)
53
+ n1.set("s1")
59
54
 
60
- should "pass the redis instance to new keys" do
61
- n1 = Nest.new("foo", @redis)
62
- n1["bar"].set("s2")
55
+ assert "s1" == n1.get
56
+ end
63
57
 
64
- assert_equal nil, n1.get
65
- assert_equal "s2", n1["bar"].get
66
- end
58
+ test "pass the redis instance to new keys" do
59
+ n1 = Nest.new("foo", @redis)
67
60
 
68
- should "PubSub" do
69
- foo = Nest.new("foo", @redis)
70
- listening = false
71
- message_received = false
61
+ assert @redis.id == n1["bar"].redis.id
62
+ end
72
63
 
73
- Thread.new do
74
- while !listening; end
75
- Nest.new("foo", Redis.new(:db => 15)).publish("")
76
- end
64
+ test "PubSub" do
65
+ foo = Nest.new("foo", @redis)
66
+ listening = false
67
+ message_received = false
77
68
 
78
- foo.subscribe do |on|
79
- on.message do
80
- message_received = true
69
+ Thread.new do
70
+ while !listening; end
71
+ Nest.new("foo", Redis.new(:db => 15)).publish("")
72
+ end
81
73
 
82
- foo.unsubscribe
83
- end
74
+ foo.subscribe do |on|
75
+ on.message do
76
+ message_received = true
84
77
 
85
- listening = true
78
+ foo.unsubscribe
86
79
  end
87
80
 
88
- assert message_received
81
+ listening = true
89
82
  end
83
+
84
+ assert message_received
90
85
  end
91
86
  end
@@ -1,3 +1,3 @@
1
1
  require "rubygems"
2
- require "contest"
2
+ require "cutest"
3
3
  require File.join(File.dirname(__FILE__), "..", "lib", "nest")
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
- - 7
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-08-05 00:00:00 -03:00
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: Generate nested namespaced keys for key-value databases.
97
+ summary: Object Oriented Keys for Redis.
70
98
  test_files: []
71
99