<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Virtuous Code &#187; respond_to</title>
	<atom:link href="http://devblog.avdi.org/tag/respond_to/feed/" rel="self" type="application/rss+xml" />
	<link>http://devblog.avdi.org</link>
	<description>&#34;The three virtues of a programmer: laziness, impatience, and hubris&#34; -- Larry Wall</description>
	<lastBuildDate>Sun, 19 May 2013 17:37:58 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Defining #method_missing and #respond_to? at the same time</title>
		<link>http://devblog.avdi.org/2011/12/07/defining-method_missing-and-respond_to-at-the-same-time/</link>
		<comments>http://devblog.avdi.org/2011/12/07/defining-method_missing-and-respond_to-at-the-same-time/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 13:00:00 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Stupid Ruby Tricks]]></category>
		<category><![CDATA[metaprogramming]]></category>
		<category><![CDATA[method_missing]]></category>
		<category><![CDATA[respond_to]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1921</guid>
		<description><![CDATA[I was reading Eloquent Ruby yesterday morning (buy a copy if you haven&#8217;t already), and it got me thinking about one of my &#8220;favorite&#8221; Ruby gotchas: defining #method_missing without a corresponding #respond_to?. E.g.: class Liar def method_missing(*args) "Oops, I lied" &#8230; <a href="http://devblog.avdi.org/2011/12/07/defining-method_missing-and-respond_to-at-the-same-time/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I was reading <a href="http://www.amazon.com/gp/product/0321584104/ref=as_li_ss_tl?ie=UTF8&amp;tag=thlafa-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0321584104">Eloquent Ruby</a> yesterday morning (buy a copy if you haven&#8217;t already), and it got me thinking about one of my &#8220;favorite&#8221; Ruby gotchas: defining <code>#method_missing</code> without a corresponding <code>#respond_to?</code>. E.g.: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Liar</span>
  <span class="org-keyword">def</span> <span class="org-function-name">method_missing</span>(*args)
    <span class="org-string">"Oops, I lied"</span>
  <span class="org-keyword">end</span>
<span class="org-keyword">end</span>

l = <span class="org-type">Liar</span>.new
l.respond_to?(<span class="org-constant">:foo</span>) <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; false</span>
l.foo <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; "Oops, I lied"</span>

</pre>
<p> The resulting code violates the Principle of Least Surprise, and often interacts in unexpected ways with other libraries. </p>
<p> I started wondering if it would be possible to define <code>#method_missing</code> and <code>#respond_to?</code> at the same time, at least for common <code>#method_missing</code> idioms. After some fiddling I came up with something that worked pretty well. Here&#8217;s how it looks: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Foo</span>
  extend <span class="org-type">MatchMethodMacros</span>

  match_method(<span class="org-string">/Amake_me_a_/</span>) <span class="org-keyword">do</span> |name, *args|
    food = <span class="org-string">/Amake_me_a_(.*)$/</span>.match(name.to_s)[1]
    <span class="org-string">"Make your own damn </span><span class="org-variable-name">#{food}</span><span class="org-string">"</span>
  <span class="org-keyword">end</span>

  match_method(<span class="org-string">/Asudo_make_me_a/</span>) <span class="org-keyword">do</span> |name, *args, &amp;block|
    food = <span class="org-string">/Asudo_make_me_a_(.*)$/</span>.match(name.to_s)[1]
    <span class="org-string">"Coming right up, one </span><span class="org-variable-name">#{food}</span><span class="org-string">"</span>
  <span class="org-keyword">end</span>

  <span class="org-keyword">def</span> <span class="org-function-name">method_missing</span>(name, *args)
    <span class="org-comment-delimiter"># </span><span class="org-comment">match_method uses modules, so we can use super to delegate to</span>
    <span class="org-comment-delimiter"># </span><span class="org-comment">the generated #method_missing definitions.</span>
    <span class="org-keyword">super</span>
  <span class="org-keyword">rescue</span> <span class="org-type">NoMethodError</span>
    <span class="org-string">"We don't do that kind of thing here"</span>
  <span class="org-keyword">end</span>
<span class="org-keyword">end</span>

foo = <span class="org-type">Foo</span>.new

foo.respond_to?(<span class="org-constant">:fix_me_a_sandwich</span>) <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; false</span>
foo.respond_to?(<span class="org-constant">:make_me_a_sandwich</span>) <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; true</span>
foo.respond_to?(<span class="org-constant">:sudo_make_me_a_sandwich</span>) <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; true</span>

foo.fix_me_a_sandwich <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; "We don't do that kind of thing here"</span>
foo.make_me_a_sandwich <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; "Make your own damn sandwich"</span>
foo.sudo_make_me_a_sandwich <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; "Coming right up, one sandwich"</span>
</pre>
<p> And here&#8217;s the implementation: </p>
<pre class="src src-ruby"><span class="org-keyword">module</span> <span class="org-type">MatchMethodMacros</span>
  <span class="org-keyword">def</span> <span class="org-function-name">match_method</span>(matcher, &amp;method_body) 
    mod = <span class="org-type">Module</span>.new <span class="org-keyword">do</span>
      define_method(<span class="org-constant">:method_missing</span>) <span class="org-keyword">do</span> |method_name, *args|
        <span class="org-keyword">if</span> matcher === method_name.to_s
          instance_exec(method_name, *args, &amp;method_body)
        <span class="org-keyword">else</span>
          <span class="org-keyword">super</span>(method_name, *args)
        <span class="org-keyword">end</span>
      <span class="org-keyword">end</span>

      define_method(<span class="org-constant">:respond_to_missing?</span>) <span class="org-keyword">do</span> |method_name, include_private|
        <span class="org-comment-delimiter"># </span><span class="org-comment">Even though this is in the #respond_to_missing? hook we</span>
        <span class="org-comment-delimiter"># </span><span class="org-comment">still need to call 'super' in case there are other included</span>
        <span class="org-comment-delimiter"># </span><span class="org-comment">modules which also define #respond_to_missing?</span>
        (matcher === method_name) || <span class="org-keyword">super</span>(method_name, include_private)
      <span class="org-keyword">end</span>
    <span class="org-keyword">end</span>
    include mod
  <span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<p> (<a href="https://gist.github.com/1440084">Also available as a Gist</a>) </p>
<p> It turned out to be a relatively straightforward bit of metaprogramming. Breaking it down, it works like this: </p>
<ol>
<li><code>match_method</code> is a &#8220;macro&#8221; &#8211; a method intended to be used at the    class or module level to define other methods. </li>
<li><code>match_method</code> takes a <code>matcher</code> (anything which responds to ===,    such as a Regexp) and a block. The matcher determines if the    missing method name has been matched. The block becomes the body of    the method. </li>
<li>An anonymous module is created to house the new methods. Putting    the methods inside their own module makes it possible to make    multiple calls to <code>match_method</code> without each one overwriting the    last one&#8217;s work, as well as for the client class to also define its    own explicit <code>method_missing</code>. </li>
<li>Inside the anonymous module, a new <code>#method_missing</code> is defined. It    uses the <code>matcher</code> to determine if the method being called is a    match, and if so, it triggers the <code>method_body</code> block to be called    in the context of the instance. Otherwise it passes to the next    <code>#method_missing</code> (which will be Ruby&#8217;s default <code>#method_missing</code>    if nothing else). </li>
<li>A method <code>#respond_to_missing?</code> is also defined, which simply    checks to see if the <code>matcher</code> matches the given method name in    <code>String</code> form. If not it passes to the next <code>#respond_to_missing?</code>    using <code>super</code>. Note that Ruby doesn&#8217;t allow use of the bare version    of <code>super</code> (which passes the original arguments along) inside a    method defined with <code>define_method</code>. Instead I have to explicitly    passa the arguments along.
<p>    <code>#respond_to_missing?</code> is the Ruby 1.9 way of hooking into    <code>respond_to?</code>. Ordinarily it would free us from the need to invoke    <code>super</code> at all, because <code>#respond_to?</code> does that before checking    <code>#respond_to_missing?</code>. But in this case we may have multiple    definitions of <code>#respond_to_missing?</code> defined in different    <code>match_method</code>-generated modules all included in the same class,    and the <code>super</code> is required to invoke all of them. </p>
<p>    If none of that made sense, I don&#8217;t blame you. This stuff    sometimes hurts my head. </p>
</li>
<li>Finally, the generated module with its <code>#method_missing</code> and    <code>#respond_to_missing?</code> methods is included into the invoking    class. </li>
</ol>
<p> The only obvious downside of this approach is that there&#8217;s no way I can find to pass a block into the <code>instance_exec</code>, so even though Ruby 1.9 allows passing blocks into blocks, it&#8217;s not possible to write <code>#match_method</code> methods which take blocks. </p>
<p> In the words of Joel Hodgson: what do you think, sirs? </p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2011/12/07/defining-method_missing-and-respond_to-at-the-same-time/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
	</channel>
</rss>
