-
-
Save olivoil/1440175 to your computer and use it in GitHub Desktop.
Defining method_missing and respond_to? in one fell swoop
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
# Do you ever define #method_missing and forget #respond_to? I sure | |
# do. It would be nice if we could do them both at the same time. | |
module MatchMethodMacros | |
def match_method(matcher, &method_body) | |
mod = Module.new do | |
define_method(:method_missing) do |method_name, *args| | |
if matcher === method_name.to_s | |
instance_exec(method_name, *args, &method_body) | |
else | |
super(method_name, *args) | |
end | |
end | |
define_method(:respond_to?) do |method_name| | |
(matcher === method_name) || super(method_name) | |
end | |
end | |
include mod | |
end | |
end | |
class Foo | |
extend MatchMethodMacros | |
match_method(/\Amake_me_a_/) do |name, *args| | |
food = /\Amake_me_a_(.*)$/.match(name.to_s)[1] | |
"Make your own damn #{food}" | |
end | |
match_method(/\Asudo_make_me_a/) do |name, *args, &block| | |
food = /\Asudo_make_me_a_(.*)$/.match(name.to_s)[1] | |
"Coming right up, one #{food}" | |
end | |
def method_missing(name, *args) | |
# match_method uses modules, so we can use super to delegate to | |
# the generated #method_missing definitions. | |
super | |
rescue NoMethodError | |
"We don't do that kind of thing here" | |
end | |
end | |
foo = Foo.new | |
foo.respond_to?(:fix_me_a_sandwich) # => false | |
foo.respond_to?(:make_me_a_sandwich) # => true | |
foo.respond_to?(:sudo_make_me_a_sandwich) # => true | |
foo.fix_me_a_sandwich # => "We don't do that kind of thing here" | |
foo.make_me_a_sandwich # => "Make your own damn sandwich" | |
foo.sudo_make_me_a_sandwich # => "Coming right up, one sandwich" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment