Skip to content

Commit

Permalink
Release v0.2.0
Browse files Browse the repository at this point in the history
Complete API re-write.
  • Loading branch information
ixti committed Jul 19, 2014
1 parent ae4137b commit ea4e96f
Show file tree
Hide file tree
Showing 21 changed files with 342 additions and 254 deletions.
46 changes: 42 additions & 4 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,61 @@ ClassLength:
CyclomaticComplexity:
Max: 6

EmptyLineBetweenDefs:
AllowAdjacentOneLineDefs: true

BlockNesting:
Max: 3

HashSyntax:
EnforcedStyle: hash_rockets

Encoding:
Enabled: false

StringLiterals:
EnforcedStyle: double_quotes

AlignParameters:
EnforcedStyle: with_fixed_indentation

IndentHash:
EnforcedStyle: consistent

PercentLiteralDelimiters:
PreferredDelimiters:
'%': ()
'%i': ()
'%q': ()
'%Q': ()
'%r': '{}'
'%s': ()
'%w': '[]'
'%W': '[]'
'%x': ()

Encoding:
Enabled: false

BracesAroundHashParameters:
Enabled: false

Documentation:
Enabled: false

EmptyLines:
# Not all trivial readers/writers can be defined with attr_* methods
TrivialAccessors:
Enabled: false

# New lambda syntax is UGLY, don't enforce it
Lambda:
Enabled: false

# Ridiculous (and IMHO useless) restriction, that makes impossible aligning
# code like this:
#
# redis.hset :k1, now
# redis.hincrby :k2, 123
SingleSpaceBeforeFirstArg:
Enabled: false

AllCops:
Include:
- Gemfile
23 changes: 13 additions & 10 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
source 'https://rubygems.org'
source "https://rubygems.org"

platforms :ruby_19, :ruby_20, :ruby_21 do
group :development do
gem "celluloid-io"
gem "guard-rspec"
end

gem "rubocop"
end

gem "rake"
gem "rspec"
gem "guard-rspec"
gem "rubocop"
gem "rspec", "~> 3.0"
gem "timecop"

gem "coveralls", :require => false
gem "simplecov", :require => false

platforms :rbx do
gem "racc"
gem "rubinius-coverage", "~> 2.0"
gem "rubysl", "~> 2.0"
end

# Specify your gem's dependencies in cachew.gemspec
gemspec
57 changes: 45 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,57 @@ Or install it yourself as:
## Usage

``` ruby
# With HashAdapter
cache = Cachew.new({})
# In-memory Hash
cache = Cachew::Hash.new

cache.has?(:foo) # => false
cache.fetch(:foo) { :bar } # => :bar
cache.fetch(:foo) { Time.now.to_i } # => 1405724687
cache.fetch(:foo) { Time.now.to_i } # => 1405724687

cache.has?(:foo) # => true
cache.fetch(:foo) { :moo } # => :bar
# With ttl
cache.fetch(:foo, :ttl => 10) { Time.now.to_i } # => 1405724689

# Before 10 seconds will expire
cache.fetch(:foo, :ttl => 10) { Time.now.to_i } # => 1405724689

# With (default) NullAdapter
cache = Cachew.new
# Once 10+ seconds pass
cache.fetch(:foo, :ttl => 10) { Time.now.to_i } # => 1405724695

cache.has?(:foo) # => false
cache.fetch(:foo) { :bar } # => :bar
# Withot cache (think of it as NullLogger)
cache = Cachew::Null.new

cache.has?(:foo) # => false
cache.fetch(:foo) { :moo } # => :moo
cache.fetch(:foo) { Time.now.to_i } # => 1405724687
cache.fetch(:foo) { Time.now.to_i } # => 1405724688
```

You can easily write your own adapters:

```
class Cachew::Redis < Cache::Adapter
def initialize(client)
@client = client
end
private
def __set__(key, val, ttl)
val = Marshal.dump val
if 0 == ttl
@client.set key, val
else
@client.setex key, val, ttl
end
end
def __get__(key)
val = @client.get(key)
val ? Marshal.load(val) : UNDEFINED
end
def __key__(*)
"cachew:#{super}"
end
end
```

## Contributing
Expand Down
6 changes: 3 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
require "bundler/gem_tasks"

require 'rspec/core/rake_task'
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new

require 'rubocop/rake_task'
Rubocop::RakeTask.new
require "rubocop/rake_task"
RuboCop::RakeTask.new

task :default => [:spec, :rubocop]
2 changes: 1 addition & 1 deletion cachew.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]

spec.add_development_dependency "bundler", "~> 1.5"
spec.add_development_dependency "bundler", "~> 1.6"
end
21 changes: 3 additions & 18 deletions lib/cachew.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
require "cachew/adapter"
require "cachew/hash"
require "cachew/null"
require "cachew/version"
require "cachew/adapters"

# Unified cache interface
class Cachew
extend Forwardable

attr_reader :adapter

def initialize(store = nil)
@adapter = Adapters.build_adapter_for store
end

def fetch(key)
has?(key) ? get(key) : set(key, yield)
end

def_delegators :adapter, :set, :get, :has?
end
78 changes: 78 additions & 0 deletions lib/cachew/adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
require "digest/md5"
require "json"

module Cachew
# Base class for Cachew adapters.
#
# @example Building custom adapters
#
# class Cachew::Redis < Cache::Adapter
# def initialize(client)
# @client = client
# end
#
# private
#
# def __set__(key, val, ttl)
# val = Marshal.dump val
#
# if 0 == ttl
# @client.set key, val
# else
# @client.setex key, val, ttl
# end
# end
#
# def __get__(key)
# val = @client.get(key)
# val ? Marshal.load(val) : UNDEFINED
# end
#
# def __key__(*)
# "cachew:#{super}"
# end
# end
#
class Adapter
# Internal constant used by `__get__` to notify that value is not in the
# cache or became stale
UNDEFINED = Object.new.freeze

# @example Usage
#
# cachew.fetch "some_key", :ttl => 60 do
# HTTP.get("http://example.com").to_s
# end
#
def fetch(key, opts = {})
key = __key__ key, opts
val = __get__ key

if UNDEFINED.equal? val
val = yield
ttl = opts.fetch(:ttl) { 0 }.to_i

__set__ key, val, ttl
end

val
end

private

# :nodoc:
def __set__(_key, _val, _ttl)
fail "Not implemented"
end

# :nodoc:
def __get__(_key)
fail "Not implemented"
end

# :nodoc:
def __key__(*args)
Digest::MD5.hexdigest JSON.dump args
end
end
end
16 changes: 0 additions & 16 deletions lib/cachew/adapters.rb

This file was deleted.

5 changes: 0 additions & 5 deletions lib/cachew/adapters/base_adapter.rb

This file was deleted.

17 changes: 0 additions & 17 deletions lib/cachew/adapters/hash_adapter.rb

This file was deleted.

17 changes: 0 additions & 17 deletions lib/cachew/adapters/null_adapter.rb

This file was deleted.

25 changes: 25 additions & 0 deletions lib/cachew/hash.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require "cachew/adapter"

module Cachew
# In-memory cache adapter.
class Hash < Adapter
# @param [#to_hash] store Underlying Hash used for storage
def initialize(store = {})
@store = store.to_hash
end

private

# :nodoc:
def __set__(key, val, ttl)
ttl = 0 >= ttl ? 0 : Time.now.to_i + ttl
@store[key] = [val, ttl]
end

# :nodoc:
def __get__(key)
val, ttl = @store[key]
ttl && (0 == ttl || ttl > Time.now.to_i) ? val : UNDEFINED
end
end
end
Loading

0 comments on commit ea4e96f

Please sign in to comment.