M
Marcin Raczkowski
If you ewer wanted to easilly cache memoizable functions (ones that
output depend ONLY on parameters given)- here's a way!
Implementation contains sweeping support for classes/modules and methods
inside those classes, ActiveRecord logger is used by memcache-client
library so I provide it becouse i'm to lazy to remove that dependency in
3rd party pugin.
If anyone shows interest i'll pack it as gem, and mayby add some stuff,
all requests are welcome
Marcin Raczkowski
www.softwarelab.eu
=========================================================================
module Memoization
# store keys for sweeping
def Memoization.add_key(key)
@keys ||= []
@keys |= [key]
end
# remove keys that belongs to given class/method
def Memoization.sweep(klass, method=nil)
reg = method ? Regexp.new("^#{klass}:#{method}") :
Regexp.new("^#{klass.to_s}")
@keys.select{|k| reg.match(k) }.each{|k| Cache.delete(k)}
end
# sugar that allows SomeClass.sweep
def sweep(method = nil)
Memoization.sweep(self, method)
end
# example usage in test case, takes names of methods to memoize
def memoize(*names)
return unless defined?(Cache)
names.each do |name|
name = name.to_s
new_name = "nc_"+name
alias_method(new_name, name)
define_method(name) do |*args|
key = "#{self.class.name}:#{name}(#{args.hash})"
Memoization.add_key(key)
Cache.get(key, 60) {
self.send(new_name.to_sym, *args)
}
end
end
end
end
# doing inclusion into module / class
class Class
include Memoization
end
class Module
include Memoization
end
# workaround for non-rails environment
unless defined?(ActiveRecord::Base)
module ActiveRecord; end
class ActiveRecord::Base;
def self.logger; Logger.new(STDOUT); end;
end
end
if __FILE__ == $0
# testcase require memcached server running on default port
require 'test/unit'
require 'rubygems'
require 'memcache'
CACHE = MemCache.new 'localhost:11211', :namespace => 'moization'
require 'memcache_util'
require 'logger'
class A
def normal(a); a; end
def random(); rand; end
memoize :normal, :random
end
class TC_MyTest < Test::Unit::TestCase
def test_behaviour
assert(A.new.normala) == A.new.normala))
assert(A.new.normala) != A.new.normalb))
rnd = A.new.random
assert(A.new.random == A.new.random)
A.sweep
assert(A.new.random != rnd)
assert(A.new.random == A.new.random)
rnd = A.new.random
A.sweeprandom)
assert(A.new.random != rnd)
assert(A.new.random == A.new.random)
end
end
end
output depend ONLY on parameters given)- here's a way!
Implementation contains sweeping support for classes/modules and methods
inside those classes, ActiveRecord logger is used by memcache-client
library so I provide it becouse i'm to lazy to remove that dependency in
3rd party pugin.
If anyone shows interest i'll pack it as gem, and mayby add some stuff,
all requests are welcome
Marcin Raczkowski
www.softwarelab.eu
=========================================================================
module Memoization
# store keys for sweeping
def Memoization.add_key(key)
@keys ||= []
@keys |= [key]
end
# remove keys that belongs to given class/method
def Memoization.sweep(klass, method=nil)
reg = method ? Regexp.new("^#{klass}:#{method}") :
Regexp.new("^#{klass.to_s}")
@keys.select{|k| reg.match(k) }.each{|k| Cache.delete(k)}
end
# sugar that allows SomeClass.sweep
def sweep(method = nil)
Memoization.sweep(self, method)
end
# example usage in test case, takes names of methods to memoize
def memoize(*names)
return unless defined?(Cache)
names.each do |name|
name = name.to_s
new_name = "nc_"+name
alias_method(new_name, name)
define_method(name) do |*args|
key = "#{self.class.name}:#{name}(#{args.hash})"
Memoization.add_key(key)
Cache.get(key, 60) {
self.send(new_name.to_sym, *args)
}
end
end
end
end
# doing inclusion into module / class
class Class
include Memoization
end
class Module
include Memoization
end
# workaround for non-rails environment
unless defined?(ActiveRecord::Base)
module ActiveRecord; end
class ActiveRecord::Base;
def self.logger; Logger.new(STDOUT); end;
end
end
if __FILE__ == $0
# testcase require memcached server running on default port
require 'test/unit'
require 'rubygems'
require 'memcache'
CACHE = MemCache.new 'localhost:11211', :namespace => 'moization'
require 'memcache_util'
require 'logger'
class A
def normal(a); a; end
def random(); rand; end
memoize :normal, :random
end
class TC_MyTest < Test::Unit::TestCase
def test_behaviour
assert(A.new.normala) == A.new.normala))
assert(A.new.normala) != A.new.normalb))
rnd = A.new.random
assert(A.new.random == A.new.random)
A.sweep
assert(A.new.random != rnd)
assert(A.new.random == A.new.random)
rnd = A.new.random
A.sweeprandom)
assert(A.new.random != rnd)
assert(A.new.random == A.new.random)
end
end
end