Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit fbc4d1b3b92eb720d4494971cfc4b84ad1d3996c @soveran committed Apr 6, 2010
Showing with 221 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +19 −0 LICENSE
  3. +125 −0 README.markdown
  4. +5 −0 Rakefile
  5. +7 −0 lib/nest.rb
  6. +10 −0 nest.gemspec
  7. +17 −0 nest.gemspec.erb
  8. +34 −0 test/nest_test.rb
  9. +3 −0 test/test_helper.rb
@@ -0,0 +1 @@
+/pkg
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Michel Martens
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
@@ -0,0 +1,125 @@
+Nest
+====
+
+Generate nested namespaced keys for key-value databases.
+
+Description
+-----------
+
+If you are familiar with databases like
+[Redis](http://code.google.com/p/redis) and libraries like [Ohm](http://ohm.keyvalue.org) or
+[redis-namespace](http://github.com/defunkt/redis-namespace), you
+already know how important it is to craft the keys that will hold the
+data.
+
+ >> @redis.set "event:3:name", "Redis Meetup"
+ >> @redis.get "event:3:name"
+ => "Redis Meetup"
+
+It is a design pattern in key-value databases to use the key to simulate
+structure, and you can read more about this in the [Twitter case
+study](http://code.google.com/p/redis/wiki/TwitterAlikeExample).
+
+Nest helps you generate those keys by providing chainable namespaces:
+
+ >> event = Nest.new("event")
+ >> @redis.set event[3][:name], "Redis Meetup"
+ >> @redis.get event[3][:name]
+ => "Redis Meetup"
+
+Usage
+-----
+
+To create a new namespace:
+
+ >> ns = Nest.new("foo")
+ => "foo"
+
+ >> ns["bar"]
+ => "foo:bar"
+
+ >> ns["bar"]["baz"]["qux"]
+ => "foo:bar:baz:qux"
+
+And you can use any object as a key, not only strings:
+
+ >> ns[:foo][42]
+ => "foo:42"
+
+In a more realistic tone, lets assume you are working with Redis and
+dealing with users:
+
+ >> event = Nest.new("event")
+ => "event"
+
+ >> redis = Redis.new
+ => #<Redis::Client...>
+
+ >> id = redis.incr(event)
+ => 1
+
+ >> redis.set event[id][:name], "Redis Meetup"
+ => "OK"
+
+ >> redis.get event[id][:name]
+ => "Redis Meetup"
+
+ >> meetup = event[id]
+ => "event:1"
+
+ >> redis.get meetup[:name]
+ => "Redis Meetup"
+
+Differences with redis-namespace
+-------------------------------
+
+[redis-namespace](http://github.com/defunkt/redis-namespace) wraps Redis
+and translates the keys back and forth transparently.
+
+Use redis-namespace when you want all your application keys to live in a
+different scope.
+
+Use Nest when you want to use the keys to represent structure.
+
+Differences with Ohm
+-------------------
+
+[Ohm](http://ohm.keyvalue.org) lets you map Ruby objects to Redis with
+little effort. It not only alleviates you from the pain of generating
+keys for each object, but also helps you when dealing with references
+between objects.
+
+Use Ohm when you want to use Redis as your database.
+
+Use Nest when mapping objects with Ohm is not possible.
+
+Installation
+------------
+
+ $ sudo gem install nest
+
+License
+-------
+
+Copyright (c) 2010 Michel Martens
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,5 @@
+task :test do
+ system "cd test && ruby nest_test.rb"
+end
+
+task :default => :test
@@ -0,0 +1,7 @@
+#! /usr/bin/env ruby
+
+class Nest < String
+ def [](key)
+ self.class.new("#{self}:#{key}")
+ end
+end
@@ -0,0 +1,10 @@
+Gem::Specification.new do |s|
+ s.name = "nest"
+ s.version = "0.0.1"
+ s.summary = "Generate nested namespaced keys for key-value databases."
+ 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."
+ s.authors = ["Michel Martens"]
+ s.email = ["michel@soveran.com"]
+ s.homepage = "http://github.com/soveran/nest"
+ s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/nest.rb", "nest.gemspec", "test/commands.rb", "test/nest_test.rb", "test/test_helper.rb"]
+end
@@ -0,0 +1,17 @@
+Gem::Specification.new do |s|
+ s.name = "nest"
+ s.version = "0.0.1"
+ s.summary = "Generate nested namespaced keys for key-value databases."
+ 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."
+ s.authors = ["Michel Martens"]
+ s.email = ["michel@soveran.com"]
+ s.homepage = "http://github.com/soveran/nest"
+ s.files = <%= Dir[
+ "LICENSE",
+ "README.markdown",
+ "Rakefile",
+ "lib/**/*.rb",
+ "*.gemspec",
+ "test/*.*"
+ ].inspect %>
+end
@@ -0,0 +1,34 @@
+require File.join(File.dirname(__FILE__), "test_helper")
+
+class TestNest < Test::Unit::TestCase
+ should "return the namespace" do
+ n1 = Nest.new("foo")
+ assert_equal "foo", n1
+ end
+
+ should "prepend the namespace" do
+ n1 = Nest.new("foo")
+ assert_equal "foo:bar", n1["bar"]
+ end
+
+ should "work in more than one level" do
+ n1 = Nest.new("foo")
+ n2 = Nest.new(n1["bar"])
+ assert_equal "foo:bar:baz", n2["baz"]
+ end
+
+ should "be chainable" do
+ n1 = Nest.new("foo")
+ assert_equal "foo:bar:baz", n1["bar"]["baz"]
+ end
+
+ should "accept symbols" do
+ n1 = Nest.new(:foo)
+ assert_equal "foo:bar", n1[:bar]
+ end
+
+ should "accept numbers" do
+ n1 = Nest.new("foo")
+ assert_equal "foo:3", n1[3]
+ end
+end
@@ -0,0 +1,3 @@
+require "rubygems"
+require "contest"
+require File.join(File.dirname(__FILE__), "..", "lib", "nest")

0 comments on commit fbc4d1b

Please sign in to comment.