Skip to content

Instantly share code, notes, and snippets.

@grossadamm
Last active August 29, 2015 14:18
Show Gist options
  • Save grossadamm/0678d7ffba50a00ce263 to your computer and use it in GitHub Desktop.
Save grossadamm/0678d7ffba50a00ce263 to your computer and use it in GitHub Desktop.
Rails cacheable has_one
module CacheableHasOne
extend ActiveSupport::Concern
included do
@build_cached_getter = ::Kernel.lambda do |cache_key, association_symbol|
alias_method "_#{association_symbol}".to_sym, association_symbol
define_method(association_symbol) do
return send("_#{association_symbol}") unless persisted?
if association(association_symbol).loaded?
return instance_variable_get("@cached_#{association_symbol}") || send("_#{association_symbol}")
end
cached_value = Rails.cache.fetch cache_key do
send("_#{association_symbol}")
end
cached_value.run_callbacks :initialize
cached_value.class.set_callback :save, :after, -> { Rails.cache.delete cache_key }
instance_variable_set("@cached_#{association_symbol}", cached_value)
association(association_symbol).loaded!
instance_variable_get("@cached_#{association_symbol}")
end
end
@build_cached_setter = ::Kernel.lambda do |cache_key, association_symbol|
alias_method "_#{association_symbol}=".to_sym, "#{association_symbol}=".to_sym
define_method "#{association_symbol}=" do |value|
Rails.cache.delete cache_key
instance_variable_set("@cached_#{association_symbol}", nil)
super(value)
end
end
def self.cacheable_has_one(association_symbol, options)
send(:has_one, association_symbol, options)
instance_variable_set("@cached_#{association_symbol}", nil)
cache_key = [self.class.name, to_param, association_symbol]
@build_cached_getter.call(cache_key, association_symbol)
@build_cached_setter.call(cache_key, association_symbol)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment