Skip to content

Commit

Permalink
Relaxing redis-namespace version dependency. Updating README.
Browse files Browse the repository at this point in the history
  • Loading branch information
kenn committed Nov 5, 2011
1 parent 35f880f commit 22baba2
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 107 deletions.
8 changes: 4 additions & 4 deletions Gemfile
@@ -1,9 +1,9 @@
source "http://rubygems.org"

gem "redis-namespace", "~> 1.0.0"
gem "redis-namespace", "~> 1.0"

group :development do
gem "rspec", "~> 2.6.0"
gem "bundler", "~> 1.0.0"
gem "jeweler", "~> 1.6.0"
gem "rspec"
gem "bundler"
gem "jeweler"
end
34 changes: 17 additions & 17 deletions Gemfile.lock
@@ -1,30 +1,30 @@
GEM
remote: http://rubygems.org/
specs:
diff-lcs (1.1.2)
diff-lcs (1.1.3)
git (1.2.5)
jeweler (1.6.0)
bundler (~> 1.0.0)
jeweler (1.6.4)
bundler (~> 1.0)
git (>= 1.2.5)
rake
rake (0.9.0)
redis (2.2.0)
redis-namespace (1.0.3)
rake (0.9.2.2)
redis (2.2.2)
redis-namespace (1.1.0)
redis (< 3.0.0)
rspec (2.6.0)
rspec-core (~> 2.6.0)
rspec-expectations (~> 2.6.0)
rspec-mocks (~> 2.6.0)
rspec-core (2.6.2)
rspec-expectations (2.6.0)
rspec (2.7.0)
rspec-core (~> 2.7.0)
rspec-expectations (~> 2.7.0)
rspec-mocks (~> 2.7.0)
rspec-core (2.7.1)
rspec-expectations (2.7.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.6.0)
rspec-mocks (2.7.0)

PLATFORMS
ruby

DEPENDENCIES
bundler (~> 1.0.0)
jeweler (~> 1.6.0)
redis-namespace (~> 1.0.0)
rspec (~> 2.6.0)
bundler
jeweler
redis-namespace (~> 1.0)
rspec
154 changes: 87 additions & 67 deletions README.md
Expand Up @@ -5,14 +5,16 @@ Class-style namespace prefixing for Redis.

With Redis Classy, class names become the prefix part of the Redis keys.

class Something < Redis::Classy
end

Something.set "foo", "bar" # equivalent of => redis.set "Something:foo", "bar"
Something.get "foo" # => redis.get "Something:foo"
=> "bar"
```ruby
class Something < Redis::Classy
end

This library contains only 33 lines of code, yet powerful when you need better abstraction on Redis objects to keep things organized.
Something.set 'foo', 'bar' # equivalent of => redis.set 'Something:foo', 'bar'
Something.get 'foo' # => redis.get 'Something:foo'
=> "bar"
```

This library contains only 30+ lines of code, yet powerful when you need better abstraction on Redis objects to keep things organized.

Requies the `redis-namespace` gem.

Expand All @@ -23,24 +25,30 @@ What's new:
Synopsis
--------

With the vanilla redis gem, you've been doing this:
With the vanilla `redis` gem, you've been doing this:

redis = Redis.new
redis.set "foo", "bar"
```ruby
redis = Redis.new
redis.set 'foo', 'bar'
```

With the redis-namespace gem, you can add a prefix in the following manner:
With the `redis-namespace` gem, you can add a prefix in the following manner:

redis_ns = Redis::Namespace.new('ns', :redis => redis)
redis_ns['foo'] = 'bar' # equivalent of => redis.set "ns:foo", "bar"
```ruby
redis_ns = Redis::Namespace.new('ns', :redis => redis)
redis_ns['foo'] = 'bar' # equivalent of => redis.set 'ns:foo', 'bar'
```

Now, with the redis-classy gem, you could finally do:

class Something < Redis::Classy
end

Something.set "foo", "bar" # equivalent of => redis.set "Prefix:foo", "bar"
Something.get "foo"
=> "bar"
```ruby
class Something < Redis::Classy
end

Something.set 'foo', 'bar' # equivalent of => redis.set 'Prefix:foo', 'bar'
Something.get 'foo'
=> "bar"
```

Install
-------
Expand All @@ -52,69 +60,81 @@ Usage

In Gemfile:

gem "redis-classy"
```ruby
gem 'redis-classy'
```

In config/initializers/redis_classy.rb:

Redis::Classy.db = Redis.new
```ruby
Redis::Classy.db = Redis.new
```

Now you can write models that inherit the Redis::Classy class, automatically prefixing keys with its class name.
You can use any Redis commands on the class, since they are simply passed to the Redis instance.

class UniqueUser < Redis::Classy
def self.nuke
self.keys.each{|key| self.del(key) }
end
end

UniqueUser.sadd "2011-02-28", @user_a.id
UniqueUser.sadd "2011-02-28", @user_b.id
UniqueUser.sadd "2011-03-01", @user_c.id

UniqueUser.smembers "2011-02-28"
=> ["123", "456"]

UniqueUser.nuke
=> ["2011-02-28", "2011-03-01"]

UniqueUser.keys
=> []
```ruby
class UniqueUser < Redis::Classy
def self.nuke
self.keys.each{|key| self.del(key) }
end
end

UniqueUser.sadd '2011-02-28', @user_a.id
UniqueUser.sadd '2011-02-28', @user_b.id
UniqueUser.sadd '2011-03-01', @user_c.id

UniqueUser.smembers '2011-02-28'
=> ["123", "456"]

UniqueUser.nuke
=> ["2011-02-28", "2011-03-01"]

UniqueUser.keys
=> []
```

In most cases you may be just fine with class methods, but by creating an instance with a key, even further binding is possible.

class Counter < Redis::Classy
def initialize(object)
super("#{object.class.name}:#{object.id}")
end
end

class Room < ActiveRecord::Base
end

@room = Room.create

counter = Counter.new(@room)
counter.incr
counter.incr
counter.get
=> "2"

counter.key
=> "Room:123"
```ruby
class Counter < Redis::Classy
def initialize(object)
super("#{object.class.name}:#{object.id}")
end
end

class Room < ActiveRecord::Base
end

@room = Room.create

counter = Counter.new(@room)
counter.incr
counter.incr
counter.get
=> "2"

counter.key
=> "Room:123"
```

You also have access to the non-namespaced, raw Redis instance via Redis::Classy

Redis::Classy.keys "UniqueUser:*"
=> ["UniqueUser:2011-02-28", "UniqueUser:2011-03-01"]

Redis::Classy.multi do
UniqueUser.sadd "2011-02-28", @user_a.id
UniqueUser.sadd "2011-02-28", @user_b.id
end
```ruby
Redis::Classy.keys 'UniqueUser:*'
=> ["UniqueUser:2011-02-28", "UniqueUser:2011-03-01"]

Redis::Classy.multi do
UniqueUser.sadd '2011-02-28', @user_a.id
UniqueUser.sadd '2011-02-28', @user_b.id
end
```

Since the "db" attribute is a class instance variable, you can dynamically assign different databases for each class.
Since the `db` attribute is a class instance variable, you can dynamically assign different databases for each class.

UniqueUser.db = Redis::Namespace.new("UniqueUser", :redis => Redis.new(:host => "another.host"))
```ruby
UniqueUser.db = Redis::Namespace.new('UniqueUser', :redis => Redis.new(:host => 'another.host'))
```

Reference
---------
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Expand Up @@ -24,5 +24,5 @@ Jeweler::RubygemsDotOrgTasks.new

task :default => :spec
task :spec do
exec "rspec spec/redis-classy_spec.rb"
exec "rspec spec"
end
6 changes: 5 additions & 1 deletion lib/redis-classy.rb
@@ -1 +1,5 @@
require File.dirname(__FILE__) + '/redis/classy'
require 'redis-namespace'

class Redis
autoload :Classy, 'redis/classy'
end
2 changes: 0 additions & 2 deletions lib/redis/classy.rb
@@ -1,5 +1,3 @@
require 'redis-namespace'

class Redis
class Classy
class << self
Expand Down
33 changes: 18 additions & 15 deletions spec/redis-classy_spec.rb → spec/redis_classy_spec.rb
Expand Up @@ -7,57 +7,60 @@ class Something < Redis::Classy
before(:each) do
Redis::Classy.flushdb
end

after(:each) do
Redis::Classy.flushdb
end

after(:all) do
Redis::Classy.quit
end

it "should prepend class name to the key" do
Something.set("foo", "bar")

Something.keys.should == ["foo"]
Redis::Classy.keys.should == ["Something:foo"]
end

it "should delegate class methods" do
Something.get("foo").should == nil
Something.set("foo", "bar")
Something.get("foo").should == "bar"
end

it "should delegate instance methods with the key binding" do
something = Something.new("foo")

something.get.should == nil
something.set("bar")
something.get.should == "bar"
end

it "should handle multi block" do
something = Something.new("foo")

Redis::Classy.multi do
Something.sadd "foo", "bar"
Something.sadd "foo", "baz"
something.sadd 1
something.sadd 2
something.sadd 3
end
Something.smembers("foo").should == ["baz", "bar"]

something.smembers.should == ['1','2','3']
end

it "should battle against mongoid" do
# Emulate notorious Mongoid::Extensions::Object::Conversions
class Object
def self.get(value)
value
end
end

# This would have returned "foo" instead of nil, unless we explicitly defined
# class methods from Redis::Namespace::COMMANDS
Something.get("foo").should == nil

class << Object
remove_method :get
end
Expand Down

0 comments on commit 22baba2

Please sign in to comment.