Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial

  • Loading branch information...
commit 0a5ac602383d9c6ed4780535834e85ca6280dff4 1 parent 29637ba
@mharris717 authored
View
5 Gemfile
@@ -10,4 +10,9 @@ group :development do
gem "bundler", "~> 1.0.0"
gem "jeweler", "~> 1.5.2"
gem "rcov", ">= 0"
+ gem 'rr'
end
+
+gem 'bson_ext'
+gem 'mharris_ext'
+gem 'mongoid'
View
56 Gemfile.lock
@@ -0,0 +1,56 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ activemodel (3.0.3)
+ activesupport (= 3.0.3)
+ builder (~> 2.1.2)
+ i18n (~> 0.4)
+ activesupport (3.0.3)
+ bson (1.2.0)
+ bson_ext (1.2.0)
+ builder (2.1.2)
+ diff-lcs (1.1.2)
+ facets (2.9.0)
+ fattr (2.2.0)
+ git (1.2.5)
+ i18n (0.5.0)
+ jeweler (1.5.2)
+ bundler (~> 1.0.0)
+ git (>= 1.2.5)
+ rake
+ mharris_ext (1.5.0)
+ facets
+ fattr
+ mongo (1.2.0)
+ bson (>= 1.2.0)
+ mongoid (2.0.0.rc.7)
+ activemodel (~> 3.0)
+ mongo (~> 1.2)
+ tzinfo (~> 0.3.22)
+ will_paginate (~> 3.0.pre)
+ rake (0.8.7)
+ rcov (0.9.9)
+ rr (1.0.2)
+ rspec (2.3.0)
+ rspec-core (~> 2.3.0)
+ rspec-expectations (~> 2.3.0)
+ rspec-mocks (~> 2.3.0)
+ rspec-core (2.3.1)
+ rspec-expectations (2.3.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.3.0)
+ tzinfo (0.3.24)
+ will_paginate (3.0.pre2)
+
+PLATFORMS
+ x86-mingw32
+
+DEPENDENCIES
+ bson_ext
+ bundler (~> 1.0.0)
+ jeweler (~> 1.5.2)
+ mharris_ext
+ mongoid
+ rcov
+ rr
+ rspec (~> 2.3.0)
View
12 lib/json_cache.rb
@@ -0,0 +1,12 @@
+require 'mharris_ext'
+require 'mongoid'
+
+Mongoid.configure do |config|
+ name = "json_cache_dev"
+ host = "mydesk"
+ config.master = Mongo::Connection.new(host).db(name)
+end
+
+%w(call_result method_cache cache_manager).each do |f|
+ require File.dirname(__FILE__) + "/json_cache/#{f}"
+end
View
21 lib/json_cache/cache_manager.rb
@@ -0,0 +1,21 @@
+module JsonCache
+ class CacheManager
+ include FromHash
+ fattr(:caches) { {} }
+ def reg(name,ops={})
+ res = self.caches[name.to_sym] = JsonCache::MethodCache.new(ops.merge(:name => name))
+ yield(res) if block_given?
+ end
+ def reg_simple(name,&b)
+ reg(name) do |c|
+ c.call_blk = b
+ end
+ end
+ def get_cache(name)
+ caches[name.to_sym] || (raise "no cache #{name}")
+ end
+ def method_missing(sym,*args,&b)
+ get_cache(sym).send(:get,*args,&b)
+ end
+ end
+end
View
8 lib/json_cache/call_result.rb
@@ -0,0 +1,8 @@
+module JsonCache
+ class CallResult
+ include Mongoid::Document
+ include Mongoid::Timestamps
+ field "_query_params", :type => Hash
+ field "_query_name"
+ end
+end
View
74 lib/json_cache/method_cache.rb
@@ -0,0 +1,74 @@
+module JsonCache
+ class MethodCache
+ include FromHash
+ attr_accessor :name, :call_blk, :class_name, :class_blk
+ def call_blk(&b)
+ if block_given?
+ @call_blk = b
+ else
+ @call_blk
+ end
+ end
+ def class_blk(&b)
+ if block_given?
+ @class_blk = b
+ else
+ @class_blk
+ end
+ end
+ def ensure_class_exists
+ eval class_name
+ rescue
+ return make_class
+ end
+ def make_class
+ b = class_blk || lambda { |x| }
+ cls = Class.new(JsonCache::CallResult,&b)
+ Object.const_set(class_name,cls)
+ cls
+ end
+ fattr(:type_class) do
+ if class_name
+ ensure_class_exists
+ else
+ JsonCache::CallResult
+ end
+ end
+ def get_existing(ops)
+ a = type_class.where('_query_params' => ops)
+ f = a.first
+ if !f
+ nil
+ elsif f['_from_array']
+ a.to_a
+ else
+ f
+ end
+ end
+ def need?(ops)
+ !get_existing(ops)
+ end
+ def create_from_raw(raw,ops,from_array)
+ cr_hash = raw.merge('_query_params' => ops, '_query_name' => name, '_from_array' => from_array)
+ type_class.create!(cr_hash)
+ end
+ def get_fresh(ops)
+ res = call_blk[ops]
+ if res.kind_of?(Array)
+ res.map { |x| create_from_raw(x,ops,true) }
+ else
+ create_from_raw(res,ops,false)
+ end
+ end
+ def get(ops)
+ if need?(ops)
+ get_fresh(ops)
+ else
+ get_existing(ops)
+ end
+ end
+ def all
+ JsonCache::CallResult.where('_query_name' => name)
+ end
+ end
+end
View
161 spec/json_cache_spec.rb
@@ -1,7 +1,164 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+if false
+ class Thing < JsonCache::CallResult
+ end
+
+ class Kernel::Thing < JsonCache::CallResult
+ end
+ JsonCache::CallResult.all.each { |x| x.destroy }
+ raise 'foo'
+end
+
describe "JsonCache" do
- it "fails" do
- fail "hey buddy, you should probably rename this file and start specing for real"
+ describe 'method cache' do
+ def mc; @mc; end
+ def mc2; @mc2; end
+ before do
+ JsonCache::CallResult.delete_all
+ @blk = lambda do |num|
+ {'num' => num*2}
+ end
+ @mc = JsonCache::MethodCache.new(:name => 'test', :call_blk => @blk)
+ end
+ after do
+ JsonCache::CallResult.delete_all
+ end
+ it 'get first' do
+ mc.get(2)['num'].should == 4
+ end
+ it 'should need' do
+ mc.should be_need(2)
+ end
+ it 'initial get should return call result' do
+ mc.get(2).should be_kind_of(JsonCache::CallResult)
+ end
+
+ describe 'already got' do
+ before do
+ mc.get(2)
+ end
+ it 'should save a call result' do
+ JsonCache::CallResult.where('_query_params' => 2).count.should == 1
+ end
+ it 'call result should have results' do
+ JsonCache::CallResult.where('_query_params' => 2).first.num.should == 4
+ end
+ it 'should not need' do
+ mc.should_not be_need(2)
+ end
+ it 'should need different query' do
+ mc.should be_need(3)
+ end
+ it 'should get result for diff query' do
+ mc.get(3)['num'].should == 6
+ end
+ it 'get again' do
+ dont_allow(mc).get_fresh(anything)
+ mc.get(2)
+ end
+ end
+
+ describe 'call blk returns array' do
+ before do
+ mc.call_blk = lambda do |num|
+ [num,num*2].map { |x| {'num' => x} }
+ end
+ end
+ it 'should return 2 CallResults' do
+ mc.get(2).map { |x| x.class }.should == [JsonCache::CallResult,JsonCache::CallResult]
+ end
+ it '2nd get should result 2 CallResults' do
+ mc.get(2)
+ mc.get(2).should be_kind_of(Array)
+ end
+ end
+
+ describe 'class block' do
+ before do
+ mc.class_name = 'Thing'
+ mc.class_blk = lambda do |x|
+ def num_plus(n)
+ num + n
+ end
+ end
+ end
+
+ it 'smoke' do
+ mc.get(2).num.should == 4
+ end
+ it 'type_class' do
+ mc.type_class.should == Thing
+ end
+ it 'call blk method' do
+ mc.get(2).num_plus(3).should == 7
+ end
+ it 'obj class' do
+ mc.get(2).should be_kind_of(Thing)
+ end
+ end
+
+ describe 'multiple caches, one with own class' do
+ before do
+ @mc2 = JsonCache::MethodCache.new(:name => 'test2', :call_blk => @blk)
+ mc2.class_name = 'Thing'
+ mc2.class_blk = lambda do |x|
+ def num_plus(n)
+ num + n
+ end
+ end
+ end
+
+ describe 'each has been called' do
+ before do
+ mc.get(2)
+ mc2.get(3)
+ end
+ it 'should be 1 thing' do
+ Thing.count.should == 1
+ mc2.all.count.should == 1
+ end
+ it 'should be 2 call results' do
+ JsonCache::CallResult.count.should == 2
+ mc.all.count.should == 1
+ end
+ end
+ end
+
+
+ it 'manager ugly test all' do
+ m = JsonCache::CacheManager.new
+ m.reg :nums, :class_name => 'Num' do |c|
+ c.call_blk do |num|
+ {'num' => num * 2}
+ end
+ c.class_blk do |unused|
+ def num_plus(n)
+ num + n
+ end
+ end
+ end
+ m.nums(2).num.should == 4
+ m.nums(2).num_plus(3).should == 7
+ m.get_cache(:nums).all.count.should == 1
+ end
+
+ it 'manager ugly test all simple' do
+ m = JsonCache::CacheManager.new
+ m.reg_simple :nums do |num|
+ {'num' => num * 2}
+ end
+
+ m.get_cache(:nums).type_class.should == JsonCache::CallResult
+ m.nums(2).num.should == 4
+
+ m.nums(2).class.should == JsonCache::CallResult
+ m.nums(2).should_not be_respond_to(:num_plus)
+ lambda { m.nums(2).num_plus(3) }.should raise_error
+
+ m.get_cache(:nums).all.count.should == 1
+ end
+
end
+
end
View
2  spec/spec_helper.rb
@@ -8,5 +8,5 @@
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
RSpec.configure do |config|
-
+ config.mock_with :rr
end

0 comments on commit 0a5ac60

Please sign in to comment.
Something went wrong with that request. Please try again.