Module: VirtualAttributeCache::ClassMethods

Defined in:
lib/virtual_attribute_cache/class_methods.rb

Instance Method Summary collapse

Instance Method Details

#cached_virtual_attribute(attribute, options = {}, &block) ⇒ Object

Sets up a before_save callback that will cache (or expire the cache of) the virtual attribute indicated by attribute. Use the :expire_if to specify when the cache will be expired. If it’s a proc that returns true with that particular record as argument, the cache will be expired:

cached_virtual_attribute(:full_name, :expire_if => Proc.new { |p| p.first_name_changed? || p.last_name_changed? }) do
  [first_name, last_name].join(' ')
end

If it’s not a proc, it will be converted to a string, suffixed with a question mark (?), and if that method returns true, the cache will be expired:

cached_virtual_attribute(:body, :expire_if => :body_textile_changed) do
  RedCloth.new(body_textile).to_html
end

The cache will be stored in whatever database column that matches the virtual attribute’s name. So you need one corresponding column for each virtual attribute you want to cache.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/virtual_attribute_cache/class_methods.rb', line 24

def cached_virtual_attribute(attribute, options = {}, &block)
  define_method attribute do
    self[attribute] || instance_eval(&block)
  end

  before_save do |record|
    if (!record.attribute_present?(attribute)) ||
       (!options[:expire_if].is_a?(Proc) && record.send("#{options[:expire_if]}?")) ||
       (options[:expire_if].is_a?(Proc) && options[:expire_if].call(record))
      record[attribute] = nil
      record.send "#{attribute}=", record.send(attribute)
    end
  end
end