Skip to content

Instantly share code, notes, and snippets.

@tashian
Created May 16, 2014 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tashian/8c699ce59d8f6c059714 to your computer and use it in GitHub Desktop.
Save tashian/8c699ce59d8f6c059714 to your computer and use it in GitHub Desktop.
redis_cacheable module: leverage RedisObjects in models
# lib/redis_cacheable.rb
module RedisCacheable
def self.included(base)
base.send(:include, Redis::Objects)
base.extend ClassMethods
end
module ClassMethods
def value(name, options = {}, &block)
super(name, options)
if block_given?
redis_accessor, setter_method = define_cache_method(:value, name, options)
# The setter_method is responsible for evaluating the
# block from hash_key and sending its result to redis
define_method(setter_method.to_s) do
send(redis_accessor).value = instance_eval(&block)
end
end
end
def int_value(name, options = {}, &block)
value(name, options, &block)
old_getter = :"_redis_#{name}"
alias_method old_getter, name
define_method(name.to_s) do
send(old_getter).to_i
end
define_method("#{name}=") do |val|
send(old_getter).value = val.to_i
end
end
def hash_key(name, options = {}, &block)
super(name, options)
if block_given?
redis_accessor, setter_method = define_cache_method(:hash_key, name, options)
# The setter_method is responsible for evaluating the
# block from hash_key and sending its result to redis
define_method(setter_method.to_s) do
send(redis_accessor).clear
result = instance_eval(&block)
result.each do |k, v|
send(redis_accessor)[k] = v
end
end
end
end
def set(name, options = {}, &block)
super(name, options)
if block_given?
redis_accessor, setter_method = define_cache_method(:set, name, options)
redis_key = redis_existence_key(setter_method)
# The setter_method is responsible for evaluating the
# block from set and sending its result to redis
define_method(setter_method.to_s) do
send(redis_accessor).clear
result = instance_eval(&block)
redis.setbit(redis_key, id, 1)
result.each do |v|
send(redis_accessor) << v
end
end
end
end
private
def redis_existence_key(setter_method)
[redis_prefix, setter_method.to_s, "existence"].join(':')
end
def define_cache_method(type, name, options)
setter_method = "update_#{name.to_s}"
redis_accessor = name
redis_key = redis_existence_key(setter_method)
# :read_through default true
unless options.delete(:read_through) == false
redis_accessor = "original #{name.to_s}"
alias_method redis_accessor, name
# This is the read-through cache method for redis
define_method(name) do
redis_object = send redis_accessor
if (type == :set && redis.getbit(redis_key, id) == 0) || (type == :hash_key && redis_object.empty?) || (type == :value && redis_object.nil?)
send setter_method
end
redis_object
end
end
[redis_accessor, setter_method]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment