<?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"
	>

<channel>
	<title>McPhage's Blog</title>
	<atom:link href="http://mcphage.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://mcphage.com</link>
	<description>If it's stupid, and it works&#8212;then it's not stupid</description>
	<pubDate>Fri, 06 Feb 2009 19:55:47 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<item>
		<title>Pattern Methods</title>
		<link>http://mcphage.com/?p=3</link>
		<comments>http://mcphage.com/?p=3#comments</comments>
		<pubDate>Thu, 10 Apr 2008 03:23:04 +0000</pubDate>
		<dc:creator>mark.josef</dc:creator>
		
		<category><![CDATA[ruby]]></category>

		<category><![CDATA[metaprogramming]]></category>

		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.mcphage.com/?p=3</guid>
		<description><![CDATA[Rails has a series of methods, find_by_*, find_all_by_*, and find_and_create_by_* where the * can be any database column, or any combination of database columns&#8211;in any order&#8211;joined by _and_.  When I first started coding in Rails, I had trouble figuring out how they worked.  Did you have to put the columns in a particular order?  Did [...]]]></description>
			<content:encoded><![CDATA[<p>Rails has a series of methods, <span style="font-weight: bold">find_by_*</span>, <span style="font-weight: bold">find_all_by_*</span>, and <span style="font-weight: bold">find_and_create_by_*</span> where the <span style="font-weight: bold">*</span> can be any database column, or any combination of database columns&#8211;in any order&#8211;joined by <span style="font-weight: bold">_and_</span>.  When I first started coding in Rails, I had trouble figuring out how they worked.  Did you have to put the columns in a particular order?  Did they have to define every single possible combination?</p>
<p>The fact that every combination worked is how I realized that they couldn&#8217;t be defining any combination&#8211;there were just too many possibilities. A bit more Rails experience let me figure out the solution&#8211;clever usage of <span style="font-weight: bold">method_missing</span>.  I had learned Ruby, but I never realized when reading about <span style="font-weight: bold">method_missing</span>, just how <span style="font-style: italic">powerful</span> it was&#8211;it seemed like another one of those &#8220;cute but why?&#8221; things. This seems like a major shift, though.  In most languages, a method is a function with a specific name.  Single name, does a particular thing.  But with method_missing, you can have an object respond to practically anything you want, regardless of whether you defined it or not.</p>
<p>So, there&#8217;s the wild and wonderful world of catching things with <span style="font-weight: bold">method_missing</span>.  But there&#8217;s slightly more narrow purpose that&#8217;s used for quite a lot of the <span style="font-weight: bold">method_missing</span> calls&#8211;method names that match a regular expression.  That&#8217;s how the <span style="font-weight: bold">find_by_*</span> and similar methods work, they look to see if they match a particular regular expression.</p>
<p>This is a good solution.  But there was always a nagging issue with these solutions for me.  They didn&#8217;t look like, or work like, any other methods out there.  You can&#8217;t test for them using <span style="font-weight: bold">respond_to?</span>, you can&#8217;t see them in the list of methods using methods or <span style="font-weight: bold">instance_methods</span>.  Ruby&#8217;s powerful reflection features are of no use for them.  Similarly, it&#8217;s a little awkward to implement.  You need to override <span style="font-weight: bold">method_missing</span>, making sure to keep your place in the chain.  It feels more hidden than just implementing a method using <span style="font-weight: bold">def</span> or <span style="font-weight: bold">define_method</span>.</p>
<p>So I created a bit more direct of a solution.  To implement a method whose name is anything that matches a regular expression (I&#8217;m calling them patterned methods), instead of calling <span style="font-weight: bold">define_method</span>, you can call <span style="font-weight: bold">define_pattern_method</span>, as in the below:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">class</span> MyClass</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">define_pattern_method /^al/ <span class="kw1">do</span> |*args|</div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># Do something here</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj = MyClass.<span class="me1">new</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">respond_to</span>? <span class="re3">:alphabet</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># =&gt; true</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">respond_to</span>? <span class="re3">:all_fall_down</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1"># =&gt; true</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">respond_to</span>? <span class="re3">:avacado</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># =&gt; false</span></div>
</li>
</ol>
</div>
<p>Okay, excellent!  But since there isn&#8217;t a single method name, how do you know what method was called?  Why, use pattern_name, of course!</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">class</span> MyClass</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">define_pattern_method /^al<span class="br0">&#40;</span>.+<span class="br0">&#41;</span>/ <span class="kw1">do</span> |*args|</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span> pattern_name, pattern_name<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#93;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj = MyClass.<span class="me1">new</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">alphabet</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># =&gt; [ &quot;alphabet&quot;, &quot;phabet&quot; ]</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">all_fall_down</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1"># =&gt; [ &quot;all_fall_down&quot;, &quot;l_fall_down&quot; ]</span></div>
</li>
</ol>
</div>
<p>Note that you can also get the groups from the match using pattern_name by passing in the index of the group.</p>
<p>Now, what about passing a block into the method?  Since inside, define_pattern_method really uses define_method, which can&#8217;t take block methods?  Well, I&#8217;ve got a solution around it.  Not a perfect solution (a better one might be to use Ruby2Ruby and class_eval, but that would make this require Ruby2Ruby), but a pretty good one:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">class</span> MyClass</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">define_pattern_method /^al/ <span class="kw1">do</span> |*args|</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> pattern_block_given?</div>
</li>
<li class="li2">
<div class="de2">pattern_block_yield<span class="br0">&#40;</span>*args<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj = MyClass.<span class="me1">new</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">alphabet</span><span class="br0">&#40;</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">&#41;</span> <span class="kw1">do</span> |a, b, c|</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>c, b, a<span class="br0">&#93;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># =&gt; [3, 2, 1]</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">alphabet</span><span class="br0">&#40;</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># =&gt; nil</span></div>
</li>
</ol>
</div>
<p>And that&#8217;s where we are now.  This is an initial attempt, so it&#8217;s not perfect.  In particular, you can&#8217;t add them to classes or modules (I&#8217;ll need to watch the Ruby Internals talk from MountainWest again).  And in terms of reflection, I&#8217;ve implemented <strong>respond_to?</strong>, <strong>Class#instance_methods</strong> and <strong>Object#methods</strong> to list the pattern methods, but hide the underlying methods.</p>
<p>Now for the fun!  Here&#8217;s some toy examples using it.  What kind of cool uses can you think of?</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">class</span> MyClass</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">define_pattern_method /<span class="br0">&#40;</span>.+<span class="br0">&#41;</span>_and_<span class="br0">&#40;</span>.+<span class="br0">&#41;</span>/ <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">send pattern_name<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">send pattern_name<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">define_pattern_method /<span class="br0">&#40;</span>.+<span class="br0">&#41;</span>_after_<span class="br0">&#40;</span>.+<span class="br0">&#41;</span>/ <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">send pattern_name<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">send pattern_name<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">define_pattern_method /^<span class="br0">&#40;</span>.+<span class="br0">&#41;</span>_<span class="br0">&#40;</span>\d+<span class="br0">&#41;</span>_times/ <span class="kw1">do</span> |*args|</div>
</li>
<li class="li1">
<div class="de1">inner_method = pattern_name <span class="nu0">1</span></div>
</li>
<li class="li2">
<div class="de2">count = pattern_name<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span>.<span class="me1">to_i</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">count.<span class="me1">times</span> <span class="br0">&#123;</span> send<span class="br0">&#40;</span>inner_method, *args<span class="br0">&#41;</span> <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">def</span> foo</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">puts</span> <span class="st0">&quot;foo called&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">def</span> bar</div>
</li>
<li class="li2">
<div class="de2"><span class="kw3">puts</span> <span class="st0">&quot;bar called&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">def</span> quux</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">puts</span> <span class="st0">&quot;quux called&quot;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">myObj.<span class="me1">foo_after_bar_and_quux_after_foo</span></div>
</li>
</ol>
</div>
<p>Prints:</p>
<pre>bar called
foo called
quux called</pre>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">myObj.<span class="me1">foo_5_times_after_bar</span></div>
</li>
</ol>
</div>
<p>Prints:</p>
<pre>bar called
foo called
foo called
foo called
foo called
foo called</pre>
<p>And very similar to Dr. Nic&#8217;s map_by_method:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">class</span> <span class="kw3">Array</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">define_pattern_method /^map_by_<span class="br0">&#40;</span><span class="br0">&#91;</span>_a-zA-Z<span class="br0">&#93;</span><span class="br0">&#91;</span>_a-zA-Z0<span class="nu0">-9</span><span class="br0">&#93;</span>+<span class="br0">&#41;</span>$/ <span class="kw1">do</span> |*args|</div>
</li>
<li class="li1">
<div class="de1">inner_methods = pattern_name<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&#8216;_then_&#8217;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">map <span class="kw1">do</span> |x|</div>
</li>
<li class="li1">
<div class="de1">inner_methods.<span class="me1">inject</span><span class="br0">&#40;</span>x<span class="br0">&#41;</span> <span class="br0">&#123;</span> |obj, meth| obj.<span class="me1">send</span><span class="br0">&#40;</span>meth, *args<span class="br0">&#41;</span> <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span><span class="nu0">1</span>, <span class="nu0">-2</span>, <span class="nu0">-3</span>, <span class="nu0">4</span><span class="br0">&#93;</span>.<span class="me1">map_by_succ_then_abs</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># =&gt; [2, 1, 2, 5]</span></div>
</li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://mcphage.com/?feed=rss2&amp;p=3</wfw:commentRss>
		</item>
	</channel>
</rss>
