class CachedEnumeration::Cache
provide cached access to enumeration values
usage: add cache_enumeration <params> to ActiveRecord
class
parameters are
:order order of items in cached_all (default: 'id') :hashed list of attributes to provide hashes for (default: [ 'id', 'name' ]; :hashed list of attributes to provide hashes for (default: [ 'id', 'name' ]; id will always be added to that list, if missing :constantize attribute to provide constants for (default: 'name') use nil, not to generate constants
cached methods are: find_from_ids( <id> ) or find_from_ids( [ <id>, <id>, … ] )
providing cached find( <id> ) or find( [ <id>, <id>, ... ] )
find_by_XY / by_XY for all hashed attributes (by_XY is deprecated) cached_all
besides constants using the upcase name are set up providing the entries
note that all objects (arrays, maps and the models themselfs) are frozen to avoid unintentional changes.
Cachability of enumerations does not imply that all enumeration access should be cached. This is a question that needs to be well thought depending on the size of the enumeration and the number of accesses to the cached data.
The by_XY finder should be avoided as the find_by_XY will be available with and without cache.
Attributes
Public Class Methods
# File lib/cached_enumeration/cached_enumeration.rb, line 36 def initialize(base, params) # p params @options=init_options(params) @cache={} #cache by keys @all=[] #cache of all @status=:uncached #can be :uncached,:cashing,:cached @klass=base #base.extend(ClassMethods) #base.reset_column_information base_singleton = class << base; self end patch_const_missing(base_singleton) if @options[:constantize] #create_find_by_methods(base_singleton) end
Public Instance Methods
# File lib/cached_enumeration/cached_enumeration.rb, line 54 def all ensure_caches @all end
forces a cache @return Boolean true is it just cached, false if it was already cached
# File lib/cached_enumeration/cached_enumeration.rb, line 74 def cache! #only load if loading not yet in progress ensure_caches if @status == :uncached end
# File lib/cached_enumeration/cached_enumeration.rb, line 79 def cached? @status==:cached end
# File lib/cached_enumeration/cached_enumeration.rb, line 87 def first @all.first end
returns a value from a cache @param String att name of the attribute @param String key value of the attribute
# File lib/cached_enumeration/cached_enumeration.rb, line 62 def get_by(att, key) ensure_caches key=key.to_i if att.to_s == "id" @cache[att.to_s][key] end
# File lib/cached_enumeration/cached_enumeration.rb, line 68 def hashed_by?(att) options[:hashed].include?(att.to_s) end
# File lib/cached_enumeration/cached_enumeration.rb, line 83 def order @options[:order] end
Private Instance Methods
# File lib/cached_enumeration/cached_enumeration.rb, line 119 def caching? @status==:caching end
# File lib/cached_enumeration/cached_enumeration.rb, line 140 def create_constants #puts "creating constants #{self.name}" proc=@options[:constantize].respond_to?(:call) @all.each do |model| const_name = if proc @options[:constantize].call(model).upcase else model.send(@options[:constantize]).upcase end @klass.const_set const_name, model end end
# File lib/cached_enumeration/cached_enumeration.rb, line 93 def ensure_caches return false if cached? || caching? @status=:caching @cache = Hash.new do |hash, key| hash[key]=Hash.new end # the next line is weird but I want to have to Array so I use select # to dereference the relation @all = @klass.order(@options[:order]).all.to_a.freeze @all.each do |entry| @options[:hashed].each do |att| @cache[att.to_s][entry.send(att)] = entry.freeze end end create_constants if @options[:constantize] @klass.logger.try(:info, "Filled cache of #{@klass.name}: #{@options.inspect}") @status=:cached true end
# File lib/cached_enumeration/cached_enumeration.rb, line 123 def init_options(params) defaults = { :order => 'id', :hashed => ['id', 'name'], :constantize => 'name', } #params check logic params_diff=params.keys - defaults.keys raise ArgumentError.new("unexpected parameters #{params_diff.inspect}, only #{defaults.keys.inspect} are understood") unless params_diff.empty? params = defaults.merge(params) params[:hashed] << 'id' unless params[:hashed].include? 'id' params[:hashed].map! do |name| name.to_s end params end
# File lib/cached_enumeration/cached_enumeration.rb, line 155 def patch_const_missing(base_singleton) # no class caching in derived classes! return if @klass.parent.respond_to? :const_missing_with_cache_enumeration @klass.extend ConstMissing base_singleton.alias_method_chain :const_missing, :cache_enumeration end