Created
May 12, 2011 03:01
-
-
Save solotimes/967860 to your computer and use it in GitHub Desktop.
Some Mongoid extensions I made, to be moved to a repository soon (with tests etc..)
This file contains 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
module Mongoid | |
# Caches the entire document in a Marshall and Redis. | |
# Defines Document#get(id), adds methods to recache document after a save. | |
# Add `include Mongoid::CachedDocument` in your model to enable the feature. | |
module CachedDocument | |
def self.included(base) | |
base.class_eval do | |
include InstanceMethods | |
extend ClassMethods | |
before_save :refresh_cache | |
class_inheritable_accessor :cached_fields | |
self.cached_fields = [:id] | |
delegate :cached_fields, :to => "self.class" | |
end | |
end | |
module ClassMethods | |
# Defines what fields can be used with cached_find (others than 'id' which is automatically added) | |
# Remember to set indexes ! | |
def cache_on(array) | |
array.each do |field| | |
cached_fields << field | |
end | |
end | |
# Get a document from an +field+==+value+ with Redis, or request the database. | |
# IE: User.cached_find(:login, 'hello') | |
def cached_find(field, value) | |
field = field.to_s unless field.class == String | |
raise "#{field} is not in cache_on" unless cached_fields.include?(field.to_sym) | |
# Trying to get the value from Redis | |
cache_hit = true ; cache_get = false | |
begin | |
redis = REDIS.get("#{self.name}:#{field}:#{value}") | |
rescue Errno::ECONNREFUSED | |
# Do nothing | |
end | |
if redis | |
begin | |
obj = Marshal.load(redis) | |
rescue TypeError | |
# Do nothing. In this case we suppose the cache was corrupted. | |
end | |
else | |
# Querying Mongo and set the cache for later use | |
cache_hit = false | |
query_field = '_id' if field == 'id' | |
obj = self.where(field => value).first | |
cache_get = true if obj && obj.refresh_cache | |
end | |
return obj | |
end | |
end | |
module InstanceMethods | |
# Dump the object in the cache. | |
def refresh_cache | |
begin | |
cached_fields.each do |field| | |
puts "Setting for #{field}" | |
value = self.send(field) | |
REDIS.set("#{self.class.name}:#{field}:#{value}", Marshal.dump(self)) | |
end | |
true | |
rescue Errno::ECONNREFUSED | |
Merb.logger.warn "REDIS - Connection Refused" | |
false | |
end | |
end | |
end | |
end | |
end |
This file contains 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
module Mongoid | |
module Permalink | |
def self.included(base) | |
base.class_eval do | |
extend ClassMethods | |
include InstanceMethods | |
before_validation :build_permalink | |
field :permalink, :type => String | |
validates_presence_of :permalink | |
class_inheritable_accessor :permalink_from | |
delegate :permalink_from, :to => "self.class" | |
self.permalink_from = [] | |
end | |
end | |
module ClassMethods | |
def will_permalink(field) | |
permalink_from << field | |
end | |
end | |
module InstanceMethods | |
def to_param | |
permalink | |
end | |
def build_permalink | |
self.permalink = self.send(permalink_from.first).to_permalink unless permalink_from.empty? | |
end | |
end | |
end | |
end |
This file contains 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
module Mongoid | |
# User.cache_get_avatar_from_id("4ad937f9957ba40429000001") | |
module RedisCache | |
def redis_cache(key, value) | |
mkey = key == :id ? '_id' : key.to_s | |
class_eval <<-RUBY, __FILE__, __LINE__+1 | |
def self.cache_get_#{value}_from_#{key}(rkey) | |
# Trying to query from Redis first | |
cache_get = false ; cache_set = false | |
begin | |
redis = REDIS.get("#{self.to_s}:" + rkey + ":#{value}") | |
cache_get = true | |
rescue Errno::ECONNREFUSED | |
end | |
# Querying Mongo and set the cache for later use | |
unless redis | |
conditions = {} | |
conditions["#{mkey.to_sym}"] = rkey | |
redis = self.where(conditions).first | |
redis = redis.send("#{value.to_sym}") if redis | |
cache_set = true if redis && cache_set_#{value}_from_#{key}(rkey, redis) | |
end | |
return redis | |
end | |
def self.cache_set_#{value}_from_#{key}(rkey, result) | |
begin | |
redis = REDIS.set("#{self.to_s}:" + rkey + ":#{value}", result) | |
return true | |
rescue Errno::ECONNREFUSED | |
return false | |
end | |
end | |
RUBY | |
end | |
end # RedisCache | |
end # Mongoid |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment