Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Make #fetch work like Ruby fetch (thx voidlock)

  • Loading branch information...
commit f65e168fa38ee1aaf78d60802df3232f66fb49ca 1 parent a305fc2
Yehuda Katz authored
9 lib/moneta.rb
View
@@ -17,7 +17,7 @@ def [](key)
super
end
- def fetch(key, default)
+ def fetch(key, default = nil, &blk)
check_expired(key)
super
end
@@ -62,4 +62,11 @@ def update_options(key, options)
end
end
end
+
+ module Defaults
+ def fetch(key, value = nil)
+ value ||= block_given? ? yield(key) : default
+ self[key] || value
+ end
+ end
end
9 lib/moneta/berkeley.rb
View
@@ -8,9 +8,10 @@
module Moneta
class Berkeley
+ include Defaults
def initialize(options={})
- file = options[:file]
+ file = @file = options[:file]
@db = Bdb::Db.new()
@db.open(nil, file, nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
unless options[:skip_expires]
@@ -18,7 +19,7 @@ def initialize(options={})
self.extend(StringExpires)
end
end
-
+
module Implementation
def key?(key)
nil | self[key]
@@ -38,10 +39,6 @@ def [](key)
@db[key]
end
- def fetch(key, default)
- self[key] || default
- end
-
def delete(key)
value = self[key]
@db.del(nil,key,0) if value
6 lib/moneta/couch.rb
View
@@ -7,6 +7,8 @@
module Moneta
class Couch
+ include Defaults
+
def initialize(options = {})
@db = ::CouchRest.database!(options[:db])
unless options[:skip_expires]
@@ -35,10 +37,6 @@ def []=(key, value)
self[key]
end
- def fetch(key, default)
- self[key] || default
- end
-
def delete(key)
value = @db.get(key)
@db.delete_doc({"_id" => value["_id"], "_rev" => value["_rev"]}) if value
92 lib/moneta/datamapper.rb
View
@@ -8,15 +8,11 @@
class MonetaHash
include DataMapper::Resource
-
- def self.default_repository_name
- :moneta
- end
-
+
property :the_key, String, :key => true
property :value, Object, :lazy => false
property :expires, Time
-
+
def self.value(key)
obj = self.get(key)
obj && obj.value
@@ -26,79 +22,93 @@ def self.value(key)
module Moneta
class DataMapper
class Expiration
- def initialize(klass)
+ def initialize(klass, repository)
@klass = klass
+ @repository = repository
end
-
+
def [](key)
if obj = get(key)
obj.expires
end
end
-
+
def []=(key, value)
obj = get(key)
obj.expires = value
- obj.save
+ obj.save(@repository)
end
-
+
def delete(key)
obj = get(key)
obj.expires = nil
- obj.save
+ obj.save(@repository)
end
-
+
private
def get(key)
- @klass.get(key)
+ repository(@repository) { @klass.get(key) }
end
end
-
+
def initialize(options = {})
- ::DataMapper.setup(:moneta, options[:setup])
- MonetaHash.auto_upgrade!
+ @repository = options.delete(:repository) || :moneta
+ ::DataMapper.setup(@repository, options[:setup])
+ repository_context { MonetaHash.auto_upgrade! }
@hash = MonetaHash
- @expiration = Expiration.new(MonetaHash)
+ @expiration = Expiration.new(MonetaHash, @repository)
end
-
+
module Implementation
def key?(key)
- !!@hash.get(key)
+ repository_context { !!@hash.get(key) }
end
-
+
def has_key?(key)
- !!@hash.get(key)
+ repository_context { !!@hash.get(key) }
end
-
+
def [](key)
- @hash.value(key)
+ repository_context { @hash.value(key) }
end
def []=(key, value)
- obj = @hash.get(key)
- if obj
- obj.update(key, value)
- else
- @hash.create(:the_key => key, :value => value)
- end
+ repository_context {
+ obj = @hash.get(key)
+ if obj
+ obj.update(key, value)
+ else
+ @hash.create(:the_key => key, :value => value)
+ end
+ }
end
-
- def fetch(key, default)
- self[key] || default
+
+ def fetch(key, value = nil)
+ repository_context {
+ value ||= block_given? ? yield(key) : default
+ self[key] || value
+ }
end
-
+
def delete(key)
- value = self[key]
- @hash.all(:the_key => key).destroy!
- value
+ repository_context {
+ value = self[key]
+ @hash.all(:the_key => key).destroy!
+ value
+ }
end
-
+
def store(key, value, options = {})
- self[key] = value
+ repository_context { self[key] = value }
end
-
+
def clear
- @hash.all.destroy!
+ repository_context { @hash.all.destroy! }
+ end
+
+ private
+ def repository_context
+ repository(@repository) { yield }
end
end
include Implementation
7 lib/moneta/file.rb
View
@@ -65,11 +65,7 @@ def []=(key, value)
file.puts(contents)
end
end
-
- def fetch(key, default)
- self[key] || default
- end
-
+
def delete(key)
value = self[key]
FileUtils.rm(path(key))
@@ -93,6 +89,7 @@ def path(key)
end
include Implementation
include Expires
+ include Defaults
end
end
5 lib/moneta/memcache.rb
View
@@ -25,8 +25,9 @@ def []=(key, value)
store(key, value)
end
- def fetch(key, default)
- self[key] || default
+ def fetch(key, value = nil)
+ value ||= block_given? ? yield(key) : default
+ self[key] || value
end
def delete(key)
8 lib/moneta/redis.rb
View
@@ -7,6 +7,8 @@
module Moneta
class Redis
+ include Defaults
+
def initialize(options = {})
@cache = ::Redis.new(options)
end
@@ -24,11 +26,7 @@ def [](key)
def []=(key, value)
store(key, value)
end
-
- def fetch(key, default)
- @cache[key] || default
- end
-
+
def delete(key)
value = @cache[key]
@cache.delete(key) if value
5 lib/moneta/rufus.rb
View
@@ -26,8 +26,9 @@ def []=(key, value)
super(key, Marshal.dump(value))
end
- def fetch(key, default)
- self[key] || default
+ def fetch(key, value = nil)
+ value ||= block_given? ? yield(key) : default
+ self[key] || value
end
def store(key, value, options = {})
5 lib/moneta/s3.rb
View
@@ -56,8 +56,9 @@ def []=(key, value)
store(key, value)
end
- def fetch(key, default)
- self[key] || default
+ def fetch(key, value = nil)
+ value ||= block_given? ? yield(key) : default
+ self[key] || value
end
def delete(key)
6 lib/moneta/sdbm.rb
View
@@ -3,6 +3,8 @@
module Moneta
class BasicSDBM < ::SDBM
+ include Defaults
+
def [](key)
if val = super
Marshal.load(val)
@@ -13,10 +15,6 @@ def []=(key, value)
super(key, Marshal.dump(value))
end
- def fetch(key, default)
- self[key] || default
- end
-
def store(key, value, options = {})
self[key] = value
end
5 lib/moneta/tyrant.rb
View
@@ -28,8 +28,9 @@ def []=(key, value)
super(key, Marshal.dump(value))
end
- def fetch(key, default)
- self[key] || default
+ def fetch(key, value = nil)
+ value ||= block_given? ? yield(key) : default
+ self[key] || value
end
def store(key, value, options = {})
3  lib/moneta/xattr.rb
View
@@ -37,7 +37,8 @@ def []=(key, value)
@hash.set(key, Marshal.dump(value))
end
- def fetch(key, value)
+ def fetch(key, value = nil)
+ value ||= block_given? ? yield(key) : default
self[key] || value
end
78 spec/moneta_datamapper_spec.rb
View
@@ -2,18 +2,78 @@
begin
require "moneta/datamapper"
-
+
describe "Moneta::DataMapper" do
- before(:each) do
- @cache = Moneta::DataMapper.new(:setup => "sqlite3::memory:")
- @cache.clear
- end
+
+ describe "default repository" do
+ before(:each) do
+ @cache = Moneta::DataMapper.new(:setup => "sqlite3::memory:")
+ @cache.clear
+ end
- after(:all) do
- MonetaHash.auto_migrate!
+ after(:all) do
+ repository(:moneta) { MonetaHash.auto_migrate! }
+ end
+
+ it_should_behave_like "a read/write Moneta cache"
+ end
+
+ describe "when :repository specified" do
+ before(:each) do
+ @cache = Moneta::DataMapper.new(:repository => :sample, :setup => "sqlite3::memory:")
+ @cache.clear
+ end
+
+ after(:all) do
+ repository(:sample) { MonetaHash.auto_migrate! }
+ end
+
+ it_should_behave_like "a read/write Moneta cache"
+ end
+
+ describe "with multple stores" do
+ before(:each) do
+ @default_cache = Moneta::DataMapper.new(:setup => "sqlite3:moneta.db")
+ @default_cache.clear
+
+ @sample_cache = Moneta::DataMapper.new(:repository => :sample, :setup => "sqlite3:sample.db")
+ @sample_cache.clear
+ end
+
+ after(:all) do
+ File.delete('moneta.db')
+ File.delete('sample.db')
+ end
+
+ # TODO should there be more tests than these?
+ it "does not cross contaminate when storing" do
+ @default_cache["key"] = "value"
+ @sample_cache["key"] = "value2"
+
+ @default_cache["key"].should == "value"
+ @sample_cache["key"].should == "value2"
+ end
+
+ it "does not cross contaminate when deleting" do
+ @default_cache["key"] = "value"
+ @sample_cache["key"] = "value2"
+
+ @default_cache.delete("key").should == "value"
+ @default_cache.key?("key").should be_false
+ @sample_cache["key"].should == "value2"
+ end
+
+ it "does not cross contaminate when expiring" do
+ @default_cache.store("key", "value", :expires_in => 2)
+ @sample_cache["key"] = "value2"
+
+ time = Time.now
+ Time.stub!(:now).and_return { time + 2 }
+
+ @default_cache["key"].should == nil
+ @sample_cache["key"].should == "value2"
+ end
end
-
- it_should_behave_like "a read/write Moneta cache"
end
rescue SystemExit
end
4 spec/shared.rb
View
@@ -43,6 +43,10 @@
@cache.fetch("key", "value").should == "value"
end
+ it "fetches a key with a block with fetch, if the key is not available" do
+ @cache.fetch("key") { |key| "value" }.should == "value"
+ end
+
it "fetches a key with a default value with fetch, if the key is available" do
@cache["key"] = "value2"
@cache.fetch("key", "value").should == "value2"
Please sign in to comment.
Something went wrong with that request. Please try again.