Skip to content

Commit

Permalink
booyeah, eager_cache is functional
Browse files Browse the repository at this point in the history
  • Loading branch information
benburkert committed Aug 7, 2008
1 parent 4110c46 commit f6a303c
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 20 deletions.
39 changes: 31 additions & 8 deletions lib/merb-cache/merb_ext/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,30 @@ def cache_action(action, conditions = {})
alias_method "_cache_#{action}_after", :_cache_after
end

def eager_cache(trigger_action, target, conditions = {})
def eager_cache(trigger_action, target = trigger_action, conditions = {}, &blk)
target, conditions = trigger_action, target if target.is_a? Hash

if target.is_a? Array
target_controller, target_action = *target
conditions[:controller] = target_controller
else
target_action = target
target_controller, target_action = self, target
end

after("_eager_cache_#{trigger_action}_after", conditions.only(:if, :unless).merge(:with => [conditions.except(:if, :unless)], :only => trigger_action))
after("_eager_cache_#{trigger_action}_after", conditions.only(:if, :unless).merge(:with => [target_controller, target_action, conditions.except(:if, :unless), blk], :only => trigger_action))
alias_method "_eager_cache_#{trigger_action}_after", :_eager_cache_after
end

def eager_dispatch(action, env = {}, blk = nil)
kontroller = new(Merb::Request.new(env))
kontroller.setup_session
kontroller._set_skip_cache

blk.call(kontroller) unless blk.nil?

kontroller._dispatch(action)

kontroller
end
end

def fetch_partial(template, opts={}, conditions = {})
Expand All @@ -52,20 +65,30 @@ def fetch_partial(template, opts={}, conditions = {})
end

def _cache_before(conditions = {})
if data = Merb::Cache[_lookup_store(conditions)].read(self, _parameters_and_conditions(conditions).first)
if @_skip_cache.nil? && data = Merb::Cache[_lookup_store(conditions)].read(self, _parameters_and_conditions(conditions).first)
throw(:halt, data)
@_cache_hit = true
end
end

def _cache_after(conditions = {})
if Merb::Cache[_lookup_store(conditions)].write(self, nil, *_parameters_and_conditions(conditions))
if @_skip_cache.nil? && Merb::Cache[_lookup_store(conditions)].write(self, nil, *_parameters_and_conditions(conditions))
@_cache_write = true
end
end

def _eager_cache_after(conditions)

def _eager_cache_after(klass, action, conditions = {}, blk = nil)
if @_skip_cache.nil?
run_later do
controller = klass.eager_dispatch(action, request.env, blk)

Merb::Cache[controller._lookup_store(conditions)].write(controller, nil, *controller._parameters_and_conditions(conditions))
end
end
end

def _set_skip_cache
@_skip_cache = true
end

def _lookup_store(conditions)
Expand Down
6 changes: 6 additions & 0 deletions spec/merb-cache/merb_ext/controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,10 @@ class TestController < Merb::Controller; end
@controller._parameters_and_conditions(:params => :foo).first.should include(:foo)
end
end

describe "#_set_skip_cache" do
it "should set @_skip_cache = true" do
lambda { @controller._set_skip_cache }.should change { @controller.instance_variable_get(:@_skip_cache) }.to(true)
end
end
end
32 changes: 32 additions & 0 deletions spec/merb-cache/stores/strategy/action_store_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require File.dirname(__FILE__) + '/../../../spec_helper'
require File.dirname(__FILE__) + '/abstract_strategy_store_spec'

require 'ruby-debug'

describe Merb::Cache::ActionStore do
it_should_behave_like 'all strategy stores'

Expand Down Expand Up @@ -87,13 +89,25 @@ class TestController < Merb::Controller; def action; end; end
end

describe "examples" do
class MLBSchedule < Merb::Controller
cache :index

def index
"MLBSchedule index"
end
end

class MLBScores < Merb::Controller
cache :index, :show
cache :overview
cache :short, :params => :page
cache :stats, :params => [:start_date, :end_date]
cache :ticker, :expire_in => 10

eager_cache :index, [MLBSchedule, :index]
eager_cache :overview, :index
eager_cache(:short, :params => :page) {|c| c.params[:page] = (c.params[:page].to_i + 1).to_s}

def index
"MLBScores index"
end
Expand Down Expand Up @@ -155,5 +169,23 @@ def ticker

@dummy.conditions("MLBScores#ticker")[:expire_in].should == 10
end

it "should eager cache MLBSchedule#index after a request to MLBScores#index" do
dispatch_to(MLBScores, :index)

@dummy.data("MLBSchedule#index").should == "MLBSchedule index"
end

it "should eager cache :index after a request to :overview" do
dispatch_to(MLBScores, :overview)

@dummy.data("MLBScores#index").should == "MLBScores index"
end

it "should eager cache the next :short page" do
dispatch_to(MLBScores, :short, :team => :bosux, :page => 4)

@dummy.data("MLBScores#short", :team => 'bosux', :page => '5').should == "MLBScores short(bosux)[5]"
end
end
end
20 changes: 17 additions & 3 deletions spec/merb-cache/stores/strategy/page_store_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class NHLScores < Merb::Controller

cache :index, :show
cache :overview
cache :short, :params => :page
cache :stats, :params => [:start_date, :end_date]

eager_cache(:index, :overview) {|c| c.request.env['REQUEST_PATH'] = c.url(:overview)}
eager_cache :overview, :index

def index
"NHLScores index"
Expand All @@ -34,12 +34,17 @@ def index
def show(team)
"NHLScores show(#{team})"
end

def overview
"NHLScores overview"
end
end

before(:each) do
Merb::Router.prepare do |r|
r.match("/").to(:controller => "nhl_scores", :action => "index").name(:index)
r.match("/show/:team").to(:controller => "nhl_scores", :action => "show").name(:show)
r.match("/overview").to(:controller => "nhl_scores", :action => "overview").name(:overview)
end
end

Expand Down Expand Up @@ -77,11 +82,20 @@ def show(team)
it "should not cache the action when a there is a query string parameter" do
dispatch_to(NHLScores, :index, :page => 2) {|c| c.request.env['REQUEST_PATH'] = url(:index); c.request.env['QUERY_STRING'] = 'page=2'}

@dummy.vault.should be_empty
@dummy.data(url(:index)).should be_nil
end

it "should not cache a POST request" do
dispatch_to(NHLScores, :index) {|c| c.request.env['REQUEST_PATH'] = url(:index); c.request.env['REQUEST_METHOD'] = 'post'}
end

it "should not eager cache during an eager cache, causing an infinit loop of eagerness" do
pending "an easy way to test run_later :("
dispatch_to(NHLScores, :index) {|c| c.request.env['REQUEST_PATH'] = url(:index)}

sleep(2) # tried a bunch of stuff, but this was the only way that workes when run with the 'spec' command, not the rake task

@dummy.data("/overview.html").should == "NHLScores overview"
end
end
end
20 changes: 11 additions & 9 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,23 @@
end

class DummyStore < Merb::Cache::AbstractStore
attr_accessor :vault, :options
cattr_accessor :vault
attr_accessor :options

def initialize(config = {})
super(config)
@options = config
@vault = {}
@@vault = {}
end

def writable?(*args)
true
end

def read(key, parameters = {})
if @vault.keys.include?(key)
@vault[key] if @vault[key].last == parameters

if @@vault.keys.include?(key)
@@vault[key].find {|data, timestamp, conditions, params| params == parameters}
end
end

Expand All @@ -50,23 +52,23 @@ def conditions(key, parameters = {})
end

def write(key, data = nil, parameters = {}, conditions = {})
@vault[key] = [data, Time.now, conditions, parameters]
(@@vault[key] ||= []) << [data, Time.now, conditions, parameters]
true
end

def fetch(key, parameters = {}, conditions = {}, &blk)
@vault[[key, parameters]] ||= blk.call
@@vault[[key, parameters]] ||= blk.call
end

def exists?(key, parameters = {})
@vault.has_key? [key, parameters]
@@vault.has_key? [key, parameters]
end

def delete(key, parameters = {})
@vault.delete([key, parameters]) unless vault[[key, parameters]].nil?
@@vault.delete([key, parameters]) unless @@vault[[key, parameters]].nil?
end

def delete_all
@vault = {}
@@vault = {}
end
end

0 comments on commit f6a303c

Please sign in to comment.