summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorEthan Rowe <ethan@endpoint.com>2009-04-06 11:34:12 -0400
committerJames Turnbull <james@lovedthanlost.net>2009-04-22 14:39:37 +1000
commit75f1923049d5e1edfd3b9e9790a96b487cdef305 (patch)
tree6cbea71de5c6c8e366b1435abb673d1d376179ff /lib
parentbab45c4a3006867c500b30df9b91b7b46c17dff9 (diff)
Initial implementation of a "cache accumulator" behavior.
Mix Puppet::Util::CacheAccumulator into an ActiveRecord-like class, and then for any attribute in that class on which you are likely to call find_or_create_by_*, specify: accumulates :foo and instead of :find_or_create_by_foo use :accumulate_by_foo. The class will cache known results keyed by values of :foo. Do an initial bulk-lookup: class.accumulate_by_foo('foo1', 'foo2', 'foo3', 'foo4')
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/util/rails/cache_accumulator.rb65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/puppet/util/rails/cache_accumulator.rb b/lib/puppet/util/rails/cache_accumulator.rb
new file mode 100644
index 000000000..7c59a5d3f
--- /dev/null
+++ b/lib/puppet/util/rails/cache_accumulator.rb
@@ -0,0 +1,65 @@
+require 'puppet/util'
+
+module Puppet::Util::CacheAccumulator
+ def self.included(klass)
+ klass.extend ClassMethods
+ end
+
+ class Base
+ attr_reader :klass, :attribute
+
+ def initialize(klass, attribute)
+ @klass = klass
+ @attribute = attribute
+ @find_or_create = "find_or_create_by_#{@attribute.to_s}".intern
+ end
+
+ def store
+ @store || reset
+ end
+
+ def reset
+ @store = {}
+ end
+
+ def find(*keys)
+ result = nil
+ if keys.length == 1
+ result = store[keys[0]] ||= @klass.send(@find_or_create, *keys)
+ else
+ found, missing = keys.partition {|k| store.include? k}
+ result = found.length
+ result += do_multi_find(missing) if missing.length > 0
+ end
+ result
+ end
+
+ def do_multi_find(keys)
+ result = 0
+ @klass.find(:all, :conditions => {@attribute => keys}).each do |obj|
+ store[obj.send(@attribute)] = obj
+ result += 1
+ end
+ result
+ end
+ end
+
+ module ClassMethods
+ def accumulates(*attributes)
+ attributes.each {|attrib| install_accumulator(attrib)}
+ end
+
+ def accumulators
+ @accumulators ||= {}
+ end
+
+ def install_accumulator(attribute)
+ self.accumulators[attribute] = Base.new(self, attribute)
+ module_eval %{
+ def self.accumulate_by_#{attribute.to_s}(*keys)
+ accumulators[:#{attribute.to_s}].find(*keys)
+ end
+ }
+ end
+ end
+end