Skip to content

Instantly share code, notes, and snippets.

@jpmckinney
Created November 1, 2010 19:25
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jpmckinney/658716 to your computer and use it in GitHub Desktop.
Save jpmckinney/658716 to your computer and use it in GitHub Desktop.
ActiveModel class with Memcache backend
# blog post: http://blog.slashpoundbang.com/post/1455548868/memcachemodel-make-any-ruby-object-that-persists-in
# No transactions or exceptions (yet).
module MemcacheModel
def self.included(base)
base.class_eval do
extend ActiveModel::Naming
extend ActiveModel::Translation
extend ActiveModel::Callbacks
extend MemcacheModel::ClassMethods
include ActiveModel::Conversion
include ActiveModel::Validations
include ActiveModel::Serializers::JSON
include ActiveModel::Serializers::Xml
define_model_callbacks :initialize, :save, :create, :update, :destroy
end
end
module ClassMethods
def i18n_scope
:memcache_model
end
def cache
raise NotImplementedError.new("#{self.class.name}#cache is not defined")
end
# ActiveRecord::FinderMethods
def exists?(key)
cache.exist?(key)
end
# ActiveRecord::FinderMethods
def find(*keys)
keys = keys.flatten.compact.uniq
result = cache.read_multi(*keys + [ :raw => true ]).map { |key, value| new(key, value) }
case keys.size
when 1
result.first
else
result
end
end
# ActiveRecord::Base
def create(key, value = nil)
object = new(key)
object.value = value
object.create # run callbacks
object
end
# ActiveRecord::Relation
def update(key, value = nil)
object = find(key)
object.value = value # @todo Exception if key not found.
object.update # run callbacks
object
end
# ActiveRecord::Relation
def destroy(key)
if key.is_a?(Array)
key.map { |one_key| destroy(one_key) }
else
find(key).destroy # @todo Exception if key not found.
end
end
# ActiveRecord::Relation
def delete(key)
if key.is_a?(Array)
key.map { |one_key| delete(one_key) }
else
cache.delete(key)
end
end
# ActiveRecord::Relation
def delete_all
cache.clear
end
def increment(key, by = 1)
if exists?(key)
cache.increment(key, by)
else
create(key, 1) && 1
end
end
def decrement(key, by = 1)
if exists?(key)
cache.decrement(key, by)
else
create(key, 0) && 0
end
end
end
attr :key
attr_accessor :value
def initialize(key, value = nil)
@key, @value = key, value
_run_initialize_callbacks
end
def attributes
@attributes ||= { 'key' => key, 'value' => value }
end
def attributes=(attributes)
@key, @value = attributes['key'], attributes['value']
end
def id
key
end
# ActiveRecord::Persistence
def new_record?
!persisted?
end
# ActiveRecord::Persistence
def persisted?
self.class.exists?(key)
end
def create
_run_create_callbacks do
save
end
end
def update
_run_update_callbacks do
save
end
end
# ActiveRecord::Persistence
def save
_run_save_callbacks do
self.class.cache.write(key, value, :raw => true)
end
end
# ActiveRecord::Persistence
def destroy
_run_destroy_callbacks do
self.class.delete(key)
end
end
# ActiveRecord::Persistence
def delete
self.class.delete(key)
end
def increment(by = 1)
self.class.increment(key, by)
end
def decrement(by = 1)
self.class.decrement(key, by)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment