Memoizable_method_missing is a project mainly written in Ruby, based on the View license.
Optimize method_missing usage
= MemoizableMethodMissing - Optimizes method_missing use
== Introduction
We Rubyists love method_missing, but it isn't always the most efficient way to do things. Following ActiveRecord's lead, we want to have the ability to create a method definition for a given missing method (that would otherwise be handled by method_missing logic) so that subsequent requests to that method do not have to get handled by method_missing.
== Notes
NOTE: This can be used in conjunction with method_missing in the case that there is some method_missing_logic that is dependant on the args and not just the method name.
NOTE: The return value of the memoize_method_missing block should be one of:
1) String -- which can be evaled into the method definition 2) Proc -- which can be set as the method definition 4) nil -- meaning the call should be forwarded along to method_missing
NOTE: Profiling with ruby-prof has shown speed improvements of 40-60% in using memoize_method_missing over just method_missing (after the initial cost of creating the method on the fly). The test was minimal and only involved a simple regex. More complex logic may result in even greater performance gains. The performance difference between using an eval'ed String and a Proc (see NOTE above) was negligible.
== Installation
gem install memoizable_method_missing
== Git Repository
http://github.com/ePublishing/memoizable_method_missing
== Usage
class Foo
extend Epublishing::MemoizableMethodMissing
def method_missing(method, *args, &block)
if method.to_s =~ /^by_array_(.*)/ and args.first == :all
do_something($1.to_sym, args.last)
else
super
end
end
memoize_method_missing do |method|
case method.to_s
when /^by_xyz_(.*)$/
"do_something #{$1.inspect}, args.first, yield"
when /^by_id_(d+)$/
id = $1.to_i
lambda { do_something(id) }
when /^by_name_(.*)$/
name = $1
lambda do |a1, a2, &block|
do_something(name, a1 * a2, block.call)
end
end
end
end
Foo.new.by_xyz_bar(42) { :foo } => do_something("bar", 42, :foo) Foo.new.by_id_33 => do_something(33) Foo.new.by_name_chris(3, 2) { :foo } => do_something('chris', 6, :foo) Foo.new.by_array_foo(:all, 7) => do_something(:foo, 7) Foo.new.by_array_foo(:bogus) => NoSuchMethodError
Author:: David McCullars mailto:[email protected] Copyright:: (C) 2011 ePublishing Licence:: GPL[http://www.gnu.org/copyleft/gpl.html]