jodosha-redis-rails 0.0.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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Luca Guidi
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,28 @@
1
+ h1. Redis store for Rails
2
+
3
+ h2. Installation
4
+
5
+ Download and install Redis from http://code.google.com/p/redis/
6
+
7
+ wget http://redis.googlecode.com/files/redis-0.091.tar.gz
8
+ tar -zxvf redis-0.091.tar.gz
9
+ cd redis-0.091
10
+ make
11
+
12
+ Install the gems
13
+
14
+ sudo gem install ezmobius-redis-rb -s http://gems.github.com
15
+ sudo gem install jodosha-redis-rails -s http://gems.github.com
16
+
17
+ h2. How to use with Rails
18
+
19
+ In your configuration files:
20
+
21
+ config.gem "jodosha-redis-rails", :source => "http://gems.github.com"
22
+ config.cache_store = :redis_store
23
+
24
+ Start Redis server, then your application.
25
+
26
+ h2. Copyright
27
+
28
+ (c) 2009 Luca Guidi - http://lucaguidi.com, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ $:.unshift 'lib'
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+ require 'spec/rake/spectask'
7
+
8
+ REDIS_RAILS_VERSION = "0.0.1"
9
+
10
+ task :default => :spec
11
+
12
+ desc 'Build and install the gem (useful for development purposes).'
13
+ task :install do
14
+ system "gem build redis-rails.gemspec"
15
+ system "sudo gem uninstall redis-rails"
16
+ system "sudo gem install --local --no-rdoc --no-ri redis-rails-#{REDIS_RAILS_VERSION}.gem"
17
+ system "rm redis-rails-*.gem"
18
+ end
19
+
20
+ Spec::Rake::SpecTask.new do |t|
21
+ t.spec_files = FileList['spec/**/*_spec.rb']
22
+ t.spec_opts = %w(-fs --color)
23
+ end
24
+
25
+ desc 'Show the file list for the gemspec file'
26
+ task :files do
27
+ puts "Files:\n #{Dir['**/*'].reject {|f| File.directory?(f)}.sort.inspect}"
28
+ puts "Test files:\n #{Dir['spec/**/*_spec.rb'].reject {|f| File.directory?(f)}.sort.inspect}"
29
+ end
@@ -0,0 +1,128 @@
1
+ module ActiveSupport
2
+ module Cache
3
+ class RedisStore < Store
4
+ # Instantiate the store.
5
+ #
6
+ # Example:
7
+ # RedisStore.new # => host: localhost, port: 6379, db: 0
8
+ # RedisStore.new "example.com" # => host: example.com, port: 6379, db: 0
9
+ # RedisStore.new "example.com:23682" # => host: example.com, port: 23682, db: 0
10
+ # RedisStore.new "example.com:23682/1" # => host: example.com, port: 23682, db: 1
11
+ def initialize(*addresses)
12
+ addresses = extract_addresses(addresses)
13
+ @data = if addresses.size > 1
14
+ DistributedMarshaledRedis.new addresses
15
+ else
16
+ MarshaledRedis.new addresses.first || {}
17
+ end
18
+ end
19
+
20
+ def write(key, value, options = nil)
21
+ super
22
+ method = options && options[:unless_exist] ? :set_unless_exists : :set
23
+ @data.send method, key, value, options
24
+ end
25
+
26
+ def read(key, options = nil)
27
+ super
28
+ @data.get key, options
29
+ end
30
+
31
+ def delete(key, options = nil)
32
+ super
33
+ @data.delete key
34
+ end
35
+
36
+ def exist?(key, options = nil)
37
+ super
38
+ @data.key? key
39
+ end
40
+
41
+ # Increment a key in the store.
42
+ #
43
+ # If the key doesn't exist it will be initialized on 0.
44
+ # If the key exist but it isn't a Fixnum it will be initialized on 0.
45
+ #
46
+ # Example:
47
+ # We have two objects in cache:
48
+ # counter # => 23
49
+ # rabbit # => #<Rabbit:0x5eee6c>
50
+ #
51
+ # cache.increment "counter"
52
+ # cache.read "counter", :raw => true # => "24"
53
+ #
54
+ # cache.increment "counter", 6
55
+ # cache.read "counter", :raw => true # => "30"
56
+ #
57
+ # cache.increment "a counter"
58
+ # cache.read "a counter", :raw => true # => "1"
59
+ #
60
+ # cache.increment "rabbit"
61
+ # cache.read "rabbit", :raw => true # => "1"
62
+ def increment(key, amount = 1)
63
+ log "increment", key, amount
64
+ @data.incr key, amount
65
+ end
66
+
67
+ # Decrement a key in the store
68
+ #
69
+ # If the key doesn't exist it will be initialized on 0.
70
+ # If the key exist but it isn't a Fixnum it will be initialized on 0.
71
+ #
72
+ # Example:
73
+ # We have two objects in cache:
74
+ # counter # => 23
75
+ # rabbit # => #<Rabbit:0x5eee6c>
76
+ #
77
+ # cache.decrement "counter"
78
+ # cache.read "counter", :raw => true # => "22"
79
+ #
80
+ # cache.decrement "counter", 2
81
+ # cache.read "counter", :raw => true # => "20"
82
+ #
83
+ # cache.decrement "a counter"
84
+ # cache.read "a counter", :raw => true # => "-1"
85
+ #
86
+ # cache.decrement "rabbit"
87
+ # cache.read "rabbit", :raw => true # => "-1"
88
+ def decrement(key, amount = 1)
89
+ log "decrement", key, amount
90
+ @data.decr key, amount
91
+ end
92
+
93
+ # Delete objects for matched keys.
94
+ #
95
+ # Example:
96
+ # cache.delete_matched "rab*"
97
+ def delete_matched(matcher, options = nil)
98
+ super
99
+ @data.keys(matcher).each { |key| @data.delete key }
100
+ end
101
+
102
+ # Clear all the data from the store.
103
+ def clear
104
+ log "clear", nil, nil
105
+ @data.flush_db
106
+ end
107
+
108
+ def stats
109
+ @data.info
110
+ end
111
+
112
+ private
113
+ def extract_addresses(addresses)
114
+ addresses = addresses.flatten.compact
115
+ addresses.inject([]) do |result, address|
116
+ host, port = address.split /\:/
117
+ port, db = port.split /\// if port
118
+ address = {}
119
+ address[:host] = host if host
120
+ address[:port] = port if port
121
+ address[:db] = db.to_i if db
122
+ result << address
123
+ result
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,8 @@
1
+ class DistributedMarshaledRedis < DistRedis
2
+ def initialize(addresses)
3
+ nodes = addresses.map do |address|
4
+ MarshaledRedis.new address
5
+ end
6
+ @ring = HashRing.new nodes
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ class MarshaledRedis < Redis
2
+ def set(key, val, options = nil)
3
+ val = Marshal.dump val unless raw?(options)
4
+ super key, val, expires_in(options)
5
+ end
6
+
7
+ def set_unless_exists(key, val, options = nil)
8
+ val = Marshal.dump val unless raw?(options)
9
+ super key, val
10
+ end
11
+
12
+ def get(key, options = nil)
13
+ result = super key
14
+ result = Marshal.load result if result && !raw?(options)
15
+ result
16
+ end
17
+
18
+ private
19
+ def raw?(options)
20
+ options && options[:raw]
21
+ end
22
+
23
+ def expires_in(options)
24
+ options[:expires_in] if options
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ require "redis"
2
+ require "dist_redis"
3
+ require "activesupport"
4
+ require "redis/marshaled_redis"
5
+ require "redis/distributed_marshaled_redis"
6
+ require "active_support/cache/redis_store"
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "redis-rails"
3
+ s.version = "0.0.1"
4
+ s.date = "2009-04-11"
5
+ s.summary = "Redis store for Rails"
6
+ s.author = "Luca Guidi"
7
+ s.email = "guidi.luca@gmail.com"
8
+ s.homepage = "http://lucaguidi.com"
9
+ s.description = "Redis store for Rails"
10
+ s.has_rdoc = true
11
+ s.files = ["MIT-LICENSE", "README.textile", "Rakefile", "lib/active_support/cache/redis_store.rb", "lib/redis-rails.rb", "lib/redis/distributed_marshaled_redis.rb", "lib/redis/marshaled_redis.rb", "redis-rails.gemspec", "spec/active_support/cache/redis_store_spec.rb", "spec/redis/distributed_marshaled_redis_spec.rb", "spec/redis/marshaled_redis_spec.rb", "spec/spec_helper.rb"]
12
+ s.test_files = ["spec/active_support/cache/redis_store_spec.rb", "spec/redis/distributed_marshaled_redis_spec.rb", "spec/redis/marshaled_redis_spec.rb"]
13
+ s.extra_rdoc_files = ["README.textile"]
14
+ end
@@ -0,0 +1,132 @@
1
+ require File.join(File.dirname(__FILE__), "/../../spec_helper")
2
+
3
+ module ActiveSupport
4
+ module Cache
5
+ describe "RedisStore" do
6
+ before(:each) do
7
+ @store = RedisStore.new
8
+ @rabbit = OpenStruct.new :name => "bunny"
9
+ @white_rabbit = OpenStruct.new :color => "white"
10
+ @store.write "rabbit", @rabbit
11
+ @store.delete "counter"
12
+ end
13
+
14
+ it "should accept connection params" do
15
+ redis = instantiate_store
16
+ redis.instance_variable_get(:@db).should == 0
17
+ redis.host.should == "localhost"
18
+ redis.port.should == "6379"
19
+
20
+ redis = instantiate_store "redis.com"
21
+ redis.host.should == "redis.com"
22
+
23
+ redis = instantiate_store "redis.com:6380"
24
+ redis.host.should == "redis.com"
25
+ redis.port.should == "6380"
26
+
27
+ redis = instantiate_store "redis.com:6380/23"
28
+ redis.instance_variable_get(:@db).should == 23
29
+ redis.host.should == "redis.com"
30
+ redis.port.should == "6380"
31
+ end
32
+
33
+ it "should instantiate a ring" do
34
+ store = RedisStore.new
35
+ store.instance_variable_get(:@data).should be_kind_of(MarshaledRedis)
36
+ store = RedisStore.new "localhost:6379/0", "localhost:6379/1"
37
+ store.instance_variable_get(:@data).should be_kind_of(DistributedMarshaledRedis)
38
+ end
39
+
40
+ it "should read the data" do
41
+ @store.read("rabbit").should === @rabbit
42
+ end
43
+
44
+ it "should write the data" do
45
+ @store.write "rabbit", @white_rabbit
46
+ @store.read("rabbit").should === @white_rabbit
47
+ end
48
+
49
+ # it "should write the data with expiration time" do
50
+ # @store.write "rabbit", @white_rabbit, :expires_in => 1.second
51
+ # @store.read("rabbit").should === @white_rabbit ; sleep 2
52
+ # @store.read("rabbit").should be_nil
53
+ # end
54
+
55
+ it "should not write data if :unless_exist option is true" do
56
+ @store.write "rabbit", @white_rabbit, :unless_exist => true
57
+ @store.read("rabbit").should === @rabbit
58
+ end
59
+
60
+ it "should read raw data" do
61
+ @store.read("rabbit", :raw => true).should == "\004\bU:\017OpenStruct{\006:\tname\"\nbunny"
62
+ end
63
+
64
+ it "should write raw data" do
65
+ @store.write "rabbit", @white_rabbit, :raw => true
66
+ @store.read("rabbit", :raw => true).should == %(#<OpenStruct color="white">)
67
+ end
68
+
69
+ it "should delete data" do
70
+ @store.delete "rabbit"
71
+ @store.read("rabbit").should be_nil
72
+ end
73
+
74
+ it "should delete matched data" do
75
+ @store.delete_matched "rabb*"
76
+ @store.read("rabbit").should be_nil
77
+ end
78
+
79
+ it "should verify existence of an object in the store" do
80
+ @store.exist?("rabbit").should be_true
81
+ @store.exist?("rab-a-dub").should be_false
82
+ end
83
+
84
+ it "should increment a key" do
85
+ 3.times { @store.increment "counter" }
86
+ @store.read("counter", :raw => true).to_i.should == 3
87
+ end
88
+
89
+ it "should decrement a key" do
90
+ 3.times { @store.increment "counter" }
91
+ 2.times { @store.decrement "counter" }
92
+ @store.read("counter", :raw => true).to_i.should == 1
93
+ end
94
+
95
+ it "should increment a key by given value" do
96
+ @store.increment "counter", 3
97
+ @store.read("counter", :raw => true).to_i.should == 3
98
+ end
99
+
100
+ it "should decrement a key by given value" do
101
+ 3.times { @store.increment "counter" }
102
+ @store.decrement "counter", 2
103
+ @store.read("counter", :raw => true).to_i.should == 1
104
+ end
105
+
106
+ it "should clear the store" do
107
+ @store.clear
108
+ @store.instance_variable_get(:@data).keys("*").should be_empty
109
+ end
110
+
111
+ it "should return store stats" do
112
+ @store.stats.should_not be_empty
113
+ end
114
+
115
+ # it "should fetch data" do
116
+ # @store.fetch("rabbit").should == @rabbit
117
+ # @store.fetch("rab-a-dab").should be_nil
118
+ # @store.fetch("rab-a-dab") { "Flora de Cana" }
119
+ # @store.fetch("rab-a-dab").should === "Flora de Cana"
120
+ # @store.fetch("rabbit", :force => true).should be_nil # force cache miss
121
+ # @store.fetch("rabbit", :force => true, :expires_in => 1.second) { @white_rabbit }
122
+ # @store.fetch("rabbit").should === @white_rabbit ; sleep 2
123
+ # @store.fetch("rabbit").should be_nil
124
+ # end
125
+
126
+ private
127
+ def instantiate_store(address = nil)
128
+ RedisStore.new(address).instance_variable_get(:@data)
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper")
2
+
3
+ describe "DistributedMarshaledRedis" do
4
+ before(:each) do
5
+ @dmr = DistributedMarshaledRedis.new [{:db => 0}, {:db => 1}]
6
+ @rabbit = OpenStruct.new :name => "bunny"
7
+ @white_rabbit = OpenStruct.new :color => "white"
8
+ @dmr.set "rabbit", @rabbit
9
+ end
10
+
11
+ after(:all) do
12
+ @dmr.ring.nodes.each { |server| server.flush_db }
13
+ end
14
+
15
+ it "should accept connection params" do
16
+ dmr = DistributedMarshaledRedis.new [ :host => "redis.com", :port => "3680", :db => 1 ]
17
+ dmr.ring.should have(1).node
18
+ mr = dmr.ring.nodes.first
19
+ mr.host.should == "redis.com"
20
+ mr.port.should == "3680"
21
+ mr.instance_variable_get(:@db).should == 1
22
+ end
23
+
24
+ it "should set an object" do
25
+ @dmr.set "rabbit", @white_rabbit
26
+ @dmr.get("rabbit").should == @white_rabbit
27
+ end
28
+
29
+ it "should get an object" do
30
+ @dmr.get("rabbit").should == @rabbit
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper")
2
+
3
+ describe "MarshaledRedis" do
4
+ before(:each) do
5
+ @mr = MarshaledRedis.new
6
+ @rabbit = OpenStruct.new :name => "bunny"
7
+ @white_rabbit = OpenStruct.new :color => "white"
8
+ @mr.set "rabbit", @rabbit
9
+ @mr.delete "rabbit2"
10
+ end
11
+
12
+ it "should unmarshal an object on get" do
13
+ @mr.get("rabbit").should === @rabbit
14
+ end
15
+
16
+ it "should marshal object on set" do
17
+ @mr.set "rabbit", @white_rabbit
18
+ @mr.get("rabbit").should === @white_rabbit
19
+ end
20
+
21
+ it "should not unmarshal object on get if raw option is true" do
22
+ @mr.get("rabbit", :raw => true).should == "\004\bU:\017OpenStruct{\006:\tname\"\nbunny"
23
+ end
24
+
25
+ it "should not marshal object on set if raw option is true" do
26
+ @mr.set "rabbit", @white_rabbit, :raw => true
27
+ @mr.get("rabbit", :raw => true).should == %(#<OpenStruct color="white">)
28
+ end
29
+
30
+ it "should not set an object if already exist" do
31
+ @mr.set_unless_exists "rabbit", @white_rabbit
32
+ @mr.get("rabbit").should === @rabbit
33
+ end
34
+
35
+ it "should marshal object on set_unless_exists" do
36
+ @mr.set_unless_exists "rabbit2", @white_rabbit
37
+ @mr.get("rabbit2").should === @white_rabbit
38
+ end
39
+
40
+ it "should not marshal object on set_unless_exists if raw option is true" do
41
+ @mr.set_unless_exists "rabbit2", @white_rabbit, :raw => true
42
+ @mr.get("rabbit2", :raw => true).should == %(#<OpenStruct color="white">)
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ $: << File.join(File.dirname(__FILE__), "/../lib")
2
+ require "rubygems"
3
+ require "ostruct"
4
+ require "spec"
5
+ require "redis"
6
+ require "redis-rails"
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jodosha-redis-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Luca Guidi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-11 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Redis store for Rails
17
+ email: guidi.luca@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.textile
24
+ files:
25
+ - MIT-LICENSE
26
+ - README.textile
27
+ - Rakefile
28
+ - lib/active_support/cache/redis_store.rb
29
+ - lib/redis-rails.rb
30
+ - lib/redis/distributed_marshaled_redis.rb
31
+ - lib/redis/marshaled_redis.rb
32
+ - redis-rails.gemspec
33
+ - spec/active_support/cache/redis_store_spec.rb
34
+ - spec/redis/distributed_marshaled_redis_spec.rb
35
+ - spec/redis/marshaled_redis_spec.rb
36
+ - spec/spec_helper.rb
37
+ has_rdoc: true
38
+ homepage: http://lucaguidi.com
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.2.0
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: Redis store for Rails
63
+ test_files:
64
+ - spec/active_support/cache/redis_store_spec.rb
65
+ - spec/redis/distributed_marshaled_redis_spec.rb
66
+ - spec/redis/marshaled_redis_spec.rb