Class: RecordCache::Dispatcher

Inherits:
Object
  • Object
show all
Defined in:
lib/record_cache/dispatcher.rb

Overview

Every model that calls cache_records will receive an instance of this class accessible through <model>.record_cache

The dispatcher is responsible for dispatching queries, record_changes and invalidation calls to the appropriate cache strategies.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base) ⇒ Dispatcher

Returns a new instance of Dispatcher.



18
19
20
21
# File 'lib/record_cache/dispatcher.rb', line 18

def initialize(base)
  @base = base
  @strategy_by_attribute = {}
end

Class Method Details

.strategy_classesObject

Retrieve all strategies ordered by fastest strategy first.

Roll your own cache strategies by extending from RecordCache::Strategy::Base, and registering it here RecordCache::Dispatcher.strategy_classes << MyStrategy



14
15
16
# File 'lib/record_cache/dispatcher.rb', line 14

def self.strategy_classes
  @strategy_classes ||= [RecordCache::Strategy::UniqueIndexCache, RecordCache::Strategy::FullTableCache, RecordCache::Strategy::IndexCache]
end

Instance Method Details

#[](attribute) ⇒ Object

Retrieve the caching strategy for the given attribute



38
39
40
# File 'lib/record_cache/dispatcher.rb', line 38

def [](attribute)
  @strategy_by_attribute[attribute]
end

#fetch(query, &block) ⇒ Object

retrieve the record(s) based on the given query (check with cacheable?(query) first)



43
44
45
46
# File 'lib/record_cache/dispatcher.rb', line 43

def fetch(query, &block)
  strategy = query && ordered_strategies.detect { |strategy| strategy.cacheable?(query) }
  strategy ? strategy.fetch(query) : yield
end

#invalidate(strategy, value = nil) ⇒ Object

Explicitly invalidate one or more records @param: strategy: the id of the strategy to invalidate (defaults to :id) @param: value: the value to send to the invalidate method of the chosen strategy



61
62
63
64
65
# File 'lib/record_cache/dispatcher.rb', line 61

def invalidate(strategy, value = nil)
  (value = strategy; strategy = :id) unless strategy.is_a?(Symbol)
  # call the invalidate method of the chosen strategy
  @strategy_by_attribute[strategy].invalidate(value) if @strategy_by_attribute[strategy]
end

#parse(options) ⇒ Object

Parse the options provided to the cache_records method and create the appropriate cache strategies.



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/record_cache/dispatcher.rb', line 24

def parse(options)
  # find the record store, possibly based on the :store option
  store = record_store(options.delete(:store))
  # dispatch the parse call to all known strategies
  Dispatcher.strategy_classes.map{ |klass| klass.parse(@base, store, options) }.flatten.compact.each do |strategy|
    raise "Multiple record cache definitions found for '#{strategy.attribute}' on #{@base.name}" if @strategy_by_attribute[strategy.attribute]
    # and keep track of all strategies
    @strategy_by_attribute[strategy.attribute] = strategy
  end
  # make sure the strategies are ordered again on next call to +ordered_strategies+
  @ordered_strategies = nil
end

#record_change(record, action) ⇒ Object

Update the version store and the record store (used by callbacks)

Parameters:

  • record

    the updated record (possibly with

  • action

    one of :create, :update or :destroy



51
52
53
54
55
56
# File 'lib/record_cache/dispatcher.rb', line 51

def record_change(record, action)
  # skip unless something has actually changed
  return if action == :update && record.previous_changes.empty?
  # dispatch the record change to all known strategies
  @strategy_by_attribute.values.each { |strategy| strategy.record_change(record, action) }
end