Class: ActiveRecord::Base

Inherits:
Object show all
Defined in:
lib/api_hammer/active_record_cache_find_by.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cache_find_by(*attribute_names) ⇒ Object

causes requests to retrieve a record by the given attributes (all of them) to be cached. this is for single records only. it is unsafe to use with a set of attributes whose values (in conjunction) may be associated with multiple records.

see .finder_cache and .find_cache= for where it is cached.

flush_find_cache is defined on the instance. it is called on save to clear an updated record from

the cache. it may also be called explicitly to clear a record from the cache.

beware of multiple application servers with different caches - a record cached in multiple will not be invalidated in all when it is saved in one.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/api_hammer/active_record_cache_find_by.rb', line 87

def cache_find_by(*attribute_names)
  unless cache_find_bys
    # initial setup
    self.cache_find_bys = Set.new
    after_update :flush_find_cache
    before_destroy :flush_find_cache
  end

  find_by = attribute_names.map do |name|
    raise(ArgumentError) unless name.is_a?(Symbol) || name.is_a?(String)
    name.to_s.dup.freeze
  end.sort.freeze

  self.cache_find_bys = (cache_find_bys | [find_by]).freeze
end

.finder_cacheObject

the cache. should be an instance of some sort of ActiveSupport::Cache::Store. by default uses Rails.cache if that exists, or creates a ActiveSupport::Cache::MemoryStore to use. set this per-model or on ActiveRecord::Base, as needed; it is inherited.



69
70
71
72
73
74
# File 'lib/api_hammer/active_record_cache_find_by.rb', line 69

def finder_cache
  # if this looks weird, it kind of is. on the first invocation of #finder_cache, we call finder_cache= 
  # which overwrites the finder_cache method, and this then calls the newly defined method. 
  self.finder_cache = (Object.const_defined?(:Rails) && ::Rails.cache) || ::ActiveSupport::Cache::MemoryStore.new
  self.finder_cache
end

.finder_cache=(val) ⇒ Object



62
63
64
# File 'lib/api_hammer/active_record_cache_find_by.rb', line 62

def finder_cache=(val)
  define_singleton_method(:finder_cache) { val }
end

Instance Method Details

#flush_find_cacheObject

clears this record from the cache used by cache_find_by



124
125
126
127
128
129
130
131
132
# File 'lib/api_hammer/active_record_cache_find_by.rb', line 124

def flush_find_cache
  self.class.send(:cache_find_bys).each do |attribute_names|
    find_attributes = attribute_names.map { |attr_name| [attr_name, attribute_was(attr_name)] }
    self.class.instance_exec(find_attributes) do |find_attributes|
      finder_cache.delete(cache_key_for(find_attributes))
    end
  end
  nil
end