Skip to content

Instantly share code, notes, and snippets.

@TMaYaD
Created November 16, 2012 07:12
Show Gist options
  • Save TMaYaD/4085031 to your computer and use it in GitHub Desktop.
Save TMaYaD/4085031 to your computer and use it in GitHub Desktop.
ActiveModel like interface for redis
# lib/redis_record/base.rb
module RedisRecord::Base
extend ActiveSupport::Concern
def save
run_callbacks :save do
success = REDIS.multi do
REDIS.mapped_hmset(key, attributes)
sorted_indices.each do |attr|
REDIS.zadd self.class.meta_key(attr), attributes[attr.to_s], id
end
end
self.persisted = (success.first == "OK")
end
end
alias save! save
def key
self.class.key(id)
end
def update_attributes(attrs)
assign_attributes attrs
save
end
def destroy
success = REDIS.multi do
REDIS.del key
sorted_indices.each do |attr|
REDIS.zrem self.class.meta_key(attr), id
end
end
success.first == 1 ? self : nil
end
module ClassMethods
def find(id)
find_by_key key id
end
def find_by_key(key)
attributes = REDIS.mapped_hmget(key, *attribute_names)
attributes['id'] && self.new(attributes).tap { |r| r.persisted = true }
end
def all
REDIS.keys("#{model_name}:*").map { |key| find_by_key key }
end
def search_by_range_on(attr)
self.sorted_indices += [attr]
define_singleton_method "find_ids_by_#{attr}" do |min, max|
REDIS.zrangebyscore(meta_key(attr), min, max)
end
end
def meta_key(attr)
['Meta', model_name, attr].join ':'
end
def key(id)
[model_name, id].join ':'
end
end
included do
extend ActiveSupport::Callbacks
define_callbacks :save
attr_accessor :persisted
end
end
# lib/redis_record/data_types.rb
module RedisRecord::DataTypes
extend ActiveSupport::Concern
module ClassMethods
def create_initializer(type, klass, defaults = {})
define_singleton_method(type) do | *list, opts |
unless opts.is_a? Hash
list << opts
opts = {}
end
opts[:type] ||= klass
list.each do |attr|
attribute attr, defaults.merge(opts)
end
end
end
end
included do
[ :integer, :boolean, :string ].each { |klass| create_initializer klass, klass.to_s.classify.constantize }
create_initializer(:datetime, DateTime)
create_initializer(:decimal, BigDecimal)
end
end
# lib/redis_record.rb
require 'active_attr'
class RedisRecord
Dir[File.expand_path("../redis_record/**/*.rb", __FILE__)].each {|f| require f}
include ActiveAttr::Model
include DataTypes
include Base
class_attribute :sorted_indices
self.sorted_indices = []
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment