Created
May 16, 2014 22:08
-
-
Save tashian/8c699ce59d8f6c059714 to your computer and use it in GitHub Desktop.
redis_cacheable module: leverage RedisObjects in models
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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