<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>Purple Workshops News and Technical Articles</title>
    <link>http://www.purpleworkshops.com/feed</link>
    <description>Purple Workshops news and technical articles.</description>
    <geo:lat>42.03618</geo:lat><geo:long>-87.732106</geo:long><image><link>http://www.purpleworkshops.com/images/logo_medium.png</link><url>http://www.feedburner.com/fb/images/pub/fb_pwrd.gif</url><title>Purple Workshops</title></image><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/purpleworkshops" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Join Us at Windy City Rails 2009</title>
      <description>&lt;p&gt;&lt;i&gt;
        Note: For best formatting, you may want to &lt;a href="http://www.purpleworkshops.com/articles/windy-city-rails-2009"&gt;view this article on the web&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;  &lt;p&gt;PurpleWorkshops will conduct the morning tutorial session at the upcoming &lt;a href="http://windycityrails.org"&gt;Windy City Rails Conference&lt;/a&gt;.  It's a 3-hour tutorial called &lt;a href="http://windycityrails.org/sessions"&gt;REST 101: Best Practices for Rails Developers&lt;/a&gt;.&lt;/p&gt;
  
  &lt;p&gt;The conference will be held on September 12, 2009 in downtown Chicago. If you register now, you can get the early bird rate of $99 for conference admission or &lt;a href="http://windycityrails.org/register"&gt;just $199 for the conference with one tutorial session&lt;/a&gt;.&lt;/p&gt;
  
  &lt;p&gt;&lt;strong&gt;Windy City Rails donates all profits to local charities, like the &lt;a href="http://www.chicagosfoodbank.org/"&gt;Greater Chicago Food Depository&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
  
  &lt;p&gt;&lt;a href="http://windycityrails.org/register"&gt;Register now&lt;/a&gt; for the conference!&lt;/p&gt;
  
  &lt;p&gt;If you're getting started with Rails and ready to take the next step, sign up for our tutorial session too.  We'll have fun and learn a lot!&lt;/p&gt;
  
  &lt;p&gt;Questions? Feel free to email me directly at &lt;a  href="mailto:&amp;#105;n&amp;#102;&amp;#111;&amp;#64;&amp;#112;&amp;#117;r&amp;#112;&amp;#108;&amp;#101;w&amp;#111;&amp;#114;k&amp;#115;&amp;#104;&amp;#111;p&amp;#115;&amp;#46;&amp;#99;&amp;#111;&amp;#109;"&gt;&amp;#105;&amp;#110;fo&amp;#64;&amp;#112;&amp;#117;&amp;#114;&amp;#112;&amp;#108;&amp;#101;&amp;#119;&amp;#111;&amp;#114;&amp;#107;&amp;#115;h&amp;#111;&amp;#112;&amp;#115;&amp;#46;c&amp;#111;&amp;#109;&lt;/a&gt;
  &lt;/p&gt;
 
 &lt;p&gt;&lt;strong&gt;See you there!&lt;/strong&gt;&lt;/p&gt;

 
&lt;p&gt;&lt;em&gt;If you're not able to attend the conference, you're also in luck. The tutorial is a shortened version of &lt;a href="/workshops/rails-for-everyone"&gt;Rails for Everyone&lt;/a&gt;.  You can &lt;a href="/workshops/rails-for-everyone"&gt;sign up to get an email when registration opens&lt;/a&gt; that will also include a discount code.&lt;/em&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=Nimg93OMZlw:xX0f3P7LiVo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=Nimg93OMZlw:xX0f3P7LiVo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=Nimg93OMZlw:xX0f3P7LiVo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=Nimg93OMZlw:xX0f3P7LiVo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=Nimg93OMZlw:xX0f3P7LiVo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=Nimg93OMZlw:xX0f3P7LiVo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/purpleworkshops/~4/Nimg93OMZlw" height="1" width="1"/&gt;</description>
      <pubDate>24 Jun 2009</pubDate>
      <link>http://feedproxy.google.com/~r/purpleworkshops/~3/Nimg93OMZlw/windy-city-rails-2009</link>
      <guid isPermaLink="false">http://www.purpleworkshops.com/articles/windy-city-rails-2009</guid>
      <dc:creator>Jeff Cohen</dc:creator>
    <feedburner:origLink>http://www.purpleworkshops.com/articles/windy-city-rails-2009</feedburner:origLink></item>
    <item>
      <title>Rails 101: Grouping Controllers in Subdirectories</title>
      <description>&lt;p&gt;&lt;i&gt;
        Note: For best formatting, you may want to &lt;a href="http://www.purpleworkshops.com/articles/grouped-controllers"&gt;view this article on the web&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Every Rails application consists of many different Ruby classes.  Rails dictates where these classes go.  For example, some classes are called &lt;emph&gt;models&lt;/emph&gt;, and Rails will expect to find them in your &lt;code&gt;app/models&lt;/code&gt; directory; &lt;emph&gt;controllers&lt;/emph&gt; go in &lt;code&gt;app/controllers&lt;/code&gt;; and so on.&lt;/p&gt;

&lt;p&gt;For large applications, the list of Ruby files in a directory may grow large, and you might wish to create subdirectories to group related classes together.  Rails lets you create subdirectories for your classes, but you need to do more than simply move them into a new subdirectory before Rails can find them and use them properly.  In this article, we'll show you how to put a controller into a subdirectory and enable Rails to find it automatically.&lt;/p&gt;

&lt;h2&gt;Grouping Controllers into an Admin Folder&lt;/h2&gt;
&lt;p&gt;Even if your application isn't very large, you may still want to group controllers into a subdirectory.  It's not uncommon to have two controllers for a particular resource: one that serves public pages, and the other to provide an administrative interface.&lt;/p&gt;

&lt;p&gt;Let's pretend our application sells tickets for a large number of venues.  The public &lt;code&gt;VenuesController&lt;/code&gt; class allows users to select a venue, get directions, view a seating chart, and so on.  But our administrative staff has different needs: they want to add new venues, delete others, and change the information pertaining to a given venue.&lt;/p&gt;

&lt;p&gt;Let's put our administrative controller into a folder named &lt;code&gt;app/controllers/admin&lt;/code&gt;. We can generate our new controller with the &lt;code&gt;generate&lt;/code&gt; command:
  
&lt;pre class="session"&gt;script/generate controller admin/venues
&lt;/pre&gt;

&lt;p&gt;Now, open up the &lt;code&gt;app/controllers/admin/venues_controller.rb&lt;/code&gt; file that was generated:&lt;/p&gt;

              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Admin::VenuesController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;That looks... familiar. But what's with the strange class name?  And if we try to browse to &lt;code&gt;/admin/venues&lt;/code&gt;, we'll get an error message.  Why can't Rails find our controller class?&lt;/p&gt;

&lt;h2&gt;Grouped Controllers Need Ruby Modules&lt;/h2&gt;

&lt;p&gt;Here's the first catch: when you move a class into a subdirectory, Rails won't see it unless it is contained inside a lexical scope that corresponds to its physical directory.  Our &lt;code&gt;VenuesController&lt;/code&gt; is in a subdirectory named &lt;code&gt;Admin&lt;/code&gt;, so we must wrap it inside a corresponding Ruby module named &lt;code&gt;Admin&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;Why does Rails make us do this?  To prevent name collisions.  We want our public &lt;code&gt;VenuesController&lt;/code&gt; to be up in the main &lt;code&gt;app/controllers&lt;/code&gt; directory, so their needs to be a way to distinguish the two classes by something other than physical location on disk.&lt;/p&gt;

&lt;p&gt;Do do you have to configure what module name will be used in each directory?  No.  Rails conventions to the rescue. The module name is assumed to be the same as the directory name.&lt;/p&gt;

&lt;p&gt;Since our file lives in the &lt;code&gt;admin/&lt;/code&gt; subdirectory, our module name is &lt;code&gt;Admin&lt;/code&gt;.  There are a couple of ways to specify that your class lives in a directory, but one of the most common ways is to simply put the module name in front of the class name, separated by two colons.  That's how we got the class name &lt;code&gt;Admin::VenuesController&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Grouped Controllers Need Namespaced Routes&lt;/h2&gt;

&lt;p&gt;And now for the second catch.  If we were putting our model into a subdirectory, we'd be done as soon as we used the right module and class name combination.  But since this is a controller, Rails also needs a way to route admin urls to our admin controllers.  To do that, we use the &lt;code&gt;namespace&lt;/code&gt; method in our routes file:&lt;/p&gt;

              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="constant"&gt;ActionController&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Routing&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Routes&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;draw&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;

  &lt;span class="comment"&gt;# Somewhere inside this block, &lt;/span&gt;
  &lt;span class="comment"&gt;# just create a namespace for the&lt;/span&gt;
  &lt;span class="comment"&gt;# admin controllers, like this:&lt;/span&gt;
  
  &lt;span class="ident"&gt;map&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;namespace&lt;/span&gt; &lt;span class="symbol"&gt;:admin&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;admin&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;admin&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;resources&lt;/span&gt; &lt;span class="symbol"&gt;:venues&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;The &lt;code&gt;namespace&lt;/code&gt; will expect a path prefix of &lt;code&gt;admin&lt;/code&gt; and also creates named routes with the same prefix.  For example, to create a link to the &lt;code&gt;Admin::VenuesController&lt;/code&gt;'s  index action, you would do something like this:&lt;/p&gt;

              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="ident"&gt;link_to&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;View all venues&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;admin_venues_path&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;To group controllers into a subdirectory, you must do two things:&lt;/p&gt;

&lt;p&gt;1. &lt;strong&gt;Wrap your controller class inside a Ruby module&lt;/strong&gt;.  The name of the module should be the same as your subdirectory name.&lt;/p&gt;
&lt;p&gt;2. &lt;strong&gt;Create a routing namespace&lt;/strong&gt; with the same name as your subdirectory name, and map your controller from inside the namespace.&lt;/p&gt;  

&lt;p&gt;And presto!  You can now browse to &lt;code&gt;/admin/venues&lt;/code&gt; and use your new controller.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=r0xNWBwZhig:zDp5sFflIWs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=r0xNWBwZhig:zDp5sFflIWs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=r0xNWBwZhig:zDp5sFflIWs:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=r0xNWBwZhig:zDp5sFflIWs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=r0xNWBwZhig:zDp5sFflIWs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=r0xNWBwZhig:zDp5sFflIWs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/purpleworkshops/~4/r0xNWBwZhig" height="1" width="1"/&gt;</description>
      <pubDate>12 Feb 2009</pubDate>
      <link>http://feedproxy.google.com/~r/purpleworkshops/~3/r0xNWBwZhig/grouped-controllers</link>
      <guid isPermaLink="false">http://www.purpleworkshops.com/articles/grouped-controllers</guid>
      <dc:creator>Jeff Cohen</dc:creator>
    <feedburner:origLink>http://www.purpleworkshops.com/articles/grouped-controllers</feedburner:origLink></item>
    <item>
      <title>Agile 101: The Simplest Thing That Could Possibly Work</title>
      <description>&lt;p&gt;&lt;i&gt;
        Note: For best formatting, you may want to &lt;a href="http://www.purpleworkshops.com/articles/simplest-thing"&gt;view this article on the web&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;	&lt;p&gt;The saying, &amp;#8220;Do the simplest thing that could possibly work,&amp;#8221; has reached legendary status in most agile circles.  When I first heard of it, I thought it was a pretty silly statement.  After all, what developer in their right mind &lt;em&gt;chooses&lt;/em&gt; to do things the hard way?  

	&lt;p&gt;A related, albeit slightly less famous agile phrase is, &amp;#8220;Solve today's problems today.&amp;#8221;  In other words, don't design a solution to a problem that doesn't really exist, based solely on a guess that it &lt;strong&gt;might&lt;/strong&gt; be a problem tomorrow.  Just solve today's problems.&lt;/p&gt;


	&lt;p&gt;It wasn't until much later that I began to understand what this simple phrase was really talking about.&lt;/p&gt;


	&lt;p&gt;If you're new to &amp;#8220;Do the simplest thing that could possibly work,&amp;#8221; and even if you &lt;em&gt;think&lt;/em&gt; your understand what it means, read on.  I'm going to show you how we implemented a feature on the PurpleWorkshops site that followed this advice to such an extreme, that you might think I'm crazy.&lt;/p&gt;


	&lt;h2&gt;The Problem&lt;/h2&gt;


	&lt;p&gt;Potential customers can get in touch with us by filling out a very simple form (&lt;a href="http://www.purpleworkshops.com/inquiries/new"&gt;you can see it here&lt;/a&gt;). Although we don't get a lot of traffic, we were getting a significant amount of spam submitted through that form before we implemented a simple Captcha system, that you now see at the bottom of the form.  Each spam submission would add rows to our database that would require cleaning out, and each would alert me - falsely - that a potential customer was contacting us.&lt;/p&gt;



	&lt;h2&gt;A Not-So-Simple Solution&lt;/h2&gt;


	&lt;p&gt;Now, I really wanted to avoid a complicated, TicketMaster-style-can-barely-see-those-stupid-letters experience that I hate so much.  But I finally couldn't avoid it any longer, and started looking into captcha strategies.&lt;/p&gt;


	&lt;p&gt;The general idea of a captcha is you present something that automated scripts probably won't understand - like a word or number sequence contained in an .png or .jpg file - and require the user to enter that word or sequence into the form.  This raises the level of confidence that whoever - or whatever - is submitting the form is a real, human person, and therefore is probably a legitimate potential customer.&lt;/p&gt;


	&lt;p&gt;There are many solutions available.  Most of them generate images on the fly, requiring you to install something like RMagick on your server. All of the solutions I looked at were fine, but&amp;#8230; complicated.  Yes, installing a plugin and following a few directions is complicated for me.  Maybe I'm just getting old.&lt;/p&gt;


	&lt;h2&gt;First Attempt At Being Simple&lt;/h2&gt;


	&lt;p&gt;Or maybe I'm just too agile.  It occurred to me, out of the blue, that I don't really need all that complexity that most captcha solutions give me.  I have a relatively low-trafic site.  The spambots are probably not going to think it worthwhile to really target my site.  So I don't need something super deluxe.  Just something to stop the simple bots.&lt;/p&gt;


	&lt;p&gt;So rather than install RMagick and generate images on the fly with some randomly-generated word pulled from a dictionary each time the page loads, maybe I could just generate a set of images and randomly present one of them using a simple image tag.&lt;/p&gt;


	&lt;p&gt;Doesn't that sounds simpler?&lt;/p&gt;


	&lt;p&gt;Wait, it gets even better.  Instead of using RMagick to generate these images, I'm just going to use (drum roll&amp;#8230;) Skitch.  Yes, I'm going to generate them by hand, say 20 of them.&lt;/p&gt;


	&lt;p&gt;I just have to give them filenames like &lt;code&gt;captcha_1.png&lt;/code&gt;, &lt;code&gt;captcha_2.png&lt;/code&gt;, and so on.  Then, to choose an image at random, I need to do something like this in my &lt;code&gt;new&lt;/code&gt; action:&lt;/p&gt;


              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="comment"&gt;# Show form to user&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;new&lt;/span&gt;
  &lt;span class="ident"&gt;random_key&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
  &lt;span class="attribute"&gt;@captcha_filename&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;captcha_&lt;span class="expr"&gt;#{random_key}&lt;/span&gt;.png&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;



	&lt;p&gt;Later in the &lt;code&gt;create&lt;/code&gt; action, I can verify that the word they enter is the same as what's shown in the image.&lt;/p&gt;


	&lt;p&gt;Of course, somewhere I'm going to have to store the correct answer.  This could be kept in the session (say, as an &lt;span class="caps"&gt;MD5&lt;/span&gt; of the answer) or on the server.&lt;/p&gt;


	&lt;p&gt;Hmmm, this is starting to feel&amp;#8230; I don't know, not &lt;em&gt;complicated&lt;/em&gt; exactly, but more hassle than I wanted.&lt;/p&gt;


	&lt;p&gt;Time to simplify again.&lt;/p&gt;


	&lt;h2&gt;The Simplest Thing That Could Possibly... you know...&lt;/h2&gt;


	&lt;p&gt;This may sound absurd at first, but I thought, what would happen if I really just did the simplest thing that could possibly work.  At least as a first pass, before I go implementing the whole solution.&lt;/p&gt;


	&lt;p&gt;What would that be?  I think the simplest thing would be to have just one image that is shown every time, and one correct, hard-coded answer.&lt;/p&gt;


	&lt;p&gt;And that's exactly the solution &lt;a href="http://www.purpleworkshops.com/inquiries/new" target="new"&gt;you see now:&lt;/a&gt; the user must correctly type the word they see in the image before our Rails app will accept the inquiry.&lt;/p&gt;


	&lt;p&gt;But now you know the secret (whoa, I hope you don't program spambots for a living).&lt;/p&gt;


	&lt;h2&gt;The Benefits&lt;/h2&gt;


	&lt;p&gt;I created the image in about 3 minutes, added an image tag and a new text field to the inquiry form in about 3 minutes, added model validation (using the correct answer as a hardcoded string) in about 1 minute.  7 minutes, and two weeks later, no spam.  Zero.&lt;/p&gt;


	&lt;p&gt;I suppose one day, maybe even tomorrow, some spambot will figure out the answer, and this solution won't work anymore.  I'll have to make things a little more complex, and maybe use the 20-image solution.  When that happens, that will become the simplest thing that could possibly work.&lt;/p&gt;


	&lt;p&gt;But remember, that's &lt;em&gt;tomorrow's problem.&lt;/em&gt; We agile developers only solve today's problems today.&lt;/p&gt;


	&lt;h2&gt;Crazy?&lt;/h2&gt;


	&lt;p&gt;Does my solution sound crazy too you?  Ok, maybe you wouldn't say it's &lt;em&gt;crazy&lt;/em&gt; - but naive?  Do you think a &amp;#8220;real&amp;#8221; solution to the problem would involve a more rigorous solution?&lt;/p&gt;


	&lt;p&gt;If so, I have one question for you.&lt;/p&gt;


	&lt;p&gt;Did I mention &lt;em&gt;we haven't gotten any spam yet&lt;/em&gt;?&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=oq7WYkWIsCA:clWYnmJ_igg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=oq7WYkWIsCA:clWYnmJ_igg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=oq7WYkWIsCA:clWYnmJ_igg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=oq7WYkWIsCA:clWYnmJ_igg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=oq7WYkWIsCA:clWYnmJ_igg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=oq7WYkWIsCA:clWYnmJ_igg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/purpleworkshops/~4/oq7WYkWIsCA" height="1" width="1"/&gt;</description>
      <pubDate> 3 Dec 2008</pubDate>
      <link>http://feedproxy.google.com/~r/purpleworkshops/~3/oq7WYkWIsCA/simplest-thing</link>
      <guid isPermaLink="false">http://www.purpleworkshops.com/articles/simplest-thing</guid>
      <dc:creator>Jeff Cohen</dc:creator>
    <feedburner:origLink>http://www.purpleworkshops.com/articles/simplest-thing</feedburner:origLink></item>
    <item>
      <title>Rails Internals: &lt;i&gt;named_scope&lt;/i&gt; Refactored</title>
      <description>&lt;p&gt;&lt;i&gt;
        Note: For best formatting, you may want to &lt;a href="http://www.purpleworkshops.com/articles/named-scope-refactored"&gt;view this article on the web&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;You've probably heard that reading someone else's code is one way to learn more Ruby, and it's true.  If you're a Rails developer, you already have a large quantity of reading material at your disposal: the Rails source itself. Reading the Rails source code is a great way to learn about Ruby idioms and techniques that you may not be using in your own applications.  
&lt;/p&gt;
&lt;div class="callout"&gt;&lt;img alt="Stop" src="/images/icons/stop.png?1247457308" /&gt;&lt;p&gt;
&lt;p&gt;Not familiar with &lt;code&gt;named_scope&lt;/code&gt;? Check the &lt;a href="http://api.rubyonrails.com/classes/ActiveRecord/NamedScope/ClassMethods.html#M001648"&gt;API documentation&lt;/a&gt; or read about it in the &lt;a href="http://guides.rails.info/finders.html#_named_scopes"&gt;official Rails guide&lt;/a&gt;.
&lt;/p&gt;&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;Some Rails code is bread-and-butter Ruby, that most developers can readily understand.  Other parts use more advanced idioms or a more densely-packed style, which might dissuade the casual developer from being able to understand the code.  That's a shame, because valuable concepts and techniques can go unnoticed and unlearned.
&lt;/p&gt;

&lt;p&gt;We're going to take a look at the implementation of &lt;strong&gt;named_scope&lt;/strong&gt;, a very popular feature of ActiveRecord that first appeared in Rails 2.1.  
&lt;/p&gt;

&lt;h2&gt;1. What is Refactoring?&lt;/h2&gt;

&lt;p&gt;&lt;emph&gt;Refactoring&lt;/emph&gt; is an essential coding discipline for every agile developer.  Refactoring is the process of taking existing code, and morphing into new code that exhibits the exact same behavior on the outside, but is cleaner, simpler, and better designed on the inside.  
&lt;/p&gt;
&lt;p&gt;Martin Fowler, author of the well-known &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201485672"&gt;Refactoring book&lt;/a&gt;, identifies many kinds of &lt;a href="http://www.refactoring.com/catalog/index.html"&gt;refactoring patterns&lt;/a&gt;.  One of the most common techniques - &lt;a href="http://www.refactoring.com/catalog/extractMethod.html"&gt;extract method&lt;/a&gt; - can help simplify a method that's trying to do too much, or whenever the _intent_ of the code isn't clear enough.  
&lt;/p&gt;
&lt;p&gt;To demonstrate, we're going to take a look at the implementation of one of the most popular features in Rails 2.1: &lt;strong&gt;named_scope&lt;/strong&gt;.  
&lt;/p&gt;
&lt;h2&gt;2. The 10-Second Rule&lt;/h2&gt;

&lt;p&gt;No, I'm not talking about the bagel you dropped on the floor. Take a look at the following code.  It's taken directly from the Rails 2.1 source code.  Can you understand it in 10 seconds or less?
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="comment"&gt;# Implementation of named_scope in Rails 2.1&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;named_scope&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{},&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sym&lt;/span&gt;
  
  &lt;span class="ident"&gt;scopes&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;parent_scope&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="constant"&gt;Scope&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;parent_scope&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt;
      &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="constant"&gt;Hash&lt;/span&gt;
        &lt;span class="ident"&gt;options&lt;/span&gt;
      &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="constant"&gt;Proc&lt;/span&gt;
        &lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;instance_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;define_method&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;scopes&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;Unless you're comfortable with some advanced Ruby concepts, this code may be pretty hard to understand.  
&lt;/p&gt;
&lt;p&gt;There are several things going on here that make this code harder to read than it ought to be.  Let's walk through them one at a time.  We'll refactor as we go, leaving us with code that will behave the same, but will be make the &lt;code&gt;named_scope&lt;/code&gt; method more readable and its intent more transparent.
&lt;/p&gt;
&lt;p&gt;The method starts innocently enough, by coercing the &lt;code&gt;name&lt;/code&gt; parameter into a symbol.  
&lt;/p&gt;
&lt;p&gt;Then we go over the cliff pretty fast.  Line 5 looks like it's going to assign a key-value pair into a hash named &lt;code&gt;scopes&lt;/code&gt;.  The key for the pair is &lt;code&gt;name&lt;/code&gt;, but the value is... well, something complicated:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;5
6
7
8
9
10
11
12&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="ident"&gt;scopes&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;parent_scope&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="constant"&gt;Scope&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;parent_scope&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="constant"&gt;Hash&lt;/span&gt;
      &lt;span class="ident"&gt;options&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="constant"&gt;Proc&lt;/span&gt;
      &lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;It's a &lt;code&gt;lambda&lt;/code&gt; that takes multiple parameters, and which will return a new &lt;code&gt;Scope&lt;/code&gt; object.  We don't know yet what the &lt;code&gt;Scope&lt;/code&gt; class does, but we don't need to worry about that for now.  Furthermore, creating this &lt;code&gt;Scope&lt;/code&gt; instance seems to require three parameters, although it may not be immediately obvious.  
&lt;/p&gt;
&lt;p&gt;The first parameter is simply the &lt;code&gt;parent_scope&lt;/code&gt; value that was received by the &lt;code&gt;lambda&lt;/code&gt;. The second, however, requires a &lt;code&gt;case&lt;/code&gt; statement to determine, and the author of this code has chosen to put the &lt;code&gt;case&lt;/code&gt; statement inline with the rest of the code. The third parameter is the &lt;code&gt;&amp;block&lt;/code&gt; parameter that the &lt;code&gt;named_scope&lt;/code&gt; method originally received.  
&lt;/p&gt;
&lt;p&gt;After some digging into the &lt;code&gt;Scope&lt;/code&gt; class, and researching where the &lt;code&gt;scopes&lt;/code&gt; hash is used, I determined that the &lt;code&gt;scopes&lt;/code&gt; hash maps the name of your named scope to a &lt;code&gt;lambda&lt;/code&gt; expression that will be executed later.
&lt;/p&gt;
&lt;h2&gt;3. Refactoring, Part 1&lt;/h2&gt;

&lt;p&gt;Let's refactor this code segment out to a well-named method that more clearly describes the author's original intent.  
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;save_scope_definition_for_later&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scopes&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;parent_scope&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="constant"&gt;Scope&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;parent_scope&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt;
      &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="constant"&gt;Hash&lt;/span&gt;
        &lt;span class="ident"&gt;options&lt;/span&gt;
      &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="constant"&gt;Proc&lt;/span&gt;
        &lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;Now we can simplify the original code a little bit:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5
6
7
8
9
10
11
12&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="comment"&gt;# New implementation after one round of refactoring&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;named_scope&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{},&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sym&lt;/span&gt;
  
  &lt;span class="ident"&gt;save_scope_definition_for_later&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  
  &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;instance_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;define_method&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;scopes&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;Wow, that helped a lot.  Less code, more transparency.  It feels a lot better already.
&lt;/p&gt;
&lt;h2&gt;4. Refactoring, Part 2&lt;/h2&gt;

&lt;p&gt;We now have less code in the &lt;code&gt;named_scope&lt;/code&gt; method. But the code that remains still feels a bit funny. Ruby methods should contain code at the same level of abstraction.  The nice-looking call to save away the scope definition is followed several lines of very detailed-looking code.  
&lt;/p&gt;
&lt;p&gt;Let's take a closer look at the remaining code:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;instance_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;define_method&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;scopes&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;There are actually two advanced Ruby idioms in use here. Suffice to say, this code will generate a new method in your model class.  The name of this new method is made to be the same as your named scope; and the implementation is actually quite simple: it first finds the appropriate scope definition that had previously been saved away, and executes it.  
&lt;/p&gt;
&lt;p&gt;Let's again factor this out to a well-named method:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;create_method_with_same_name_as_scope&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;instance_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;define_method&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;scopes&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;
 

&lt;p&gt;And now, the &lt;code&gt;named_scope&lt;/code&gt; method has been reduced to this:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5
6&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="comment"&gt;# Clearer code&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;named_scope&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{},&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sym&lt;/span&gt; 
  &lt;span class="ident"&gt;save_scope_definition_for_later&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;create_method_with_same_name_as_scope&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;We can even do away with that reassignment of the &lt;code&gt;name&lt;/code&gt; variable as well, and perform the conversion on the fly:
&lt;/p&gt;

              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="comment"&gt;# Refactored version&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;named_scope&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{},&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;save_scope_definition_for_later&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;block&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;create_method_with_same_name_as_scope&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sym&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p/&gt;

&lt;h2&gt;5. What Did We Learn?&lt;/h2&gt;

&lt;p&gt;Imagine if our final version of the &lt;code&gt;named_scope&lt;/code&gt; was the _first_ version you saw.  You'd probably have a much easier time understanding how it works because there are two methods, each descriptively named, that provide insight into their intent. 
&lt;/p&gt;
&lt;p&gt;Refactoring is great way to learn code that you don't understand.  Begin slowly, and work to understand what the code does.  As you gain understanding, you may find that extracting out the more complicated segments into well-named methods will bring a level of clarity that you did not have when you started.
&lt;/p&gt;
&lt;div class="callout"&gt;&lt;img alt="Note" src="/images/icons/note.png?1247457308" /&gt;&lt;p&gt;&lt;p&gt;For a complete introduction to the practice of refactoring, we recommend Martin Fowler's seminal work, &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201485672"&gt;Refactoring: Improving the Design of Existing Code&lt;/a&gt;.&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;

&lt;!--
  
--&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=FwCEoCm3wrg:RyQzejYiNpM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=FwCEoCm3wrg:RyQzejYiNpM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=FwCEoCm3wrg:RyQzejYiNpM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=FwCEoCm3wrg:RyQzejYiNpM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=FwCEoCm3wrg:RyQzejYiNpM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=FwCEoCm3wrg:RyQzejYiNpM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/purpleworkshops/~4/FwCEoCm3wrg" height="1" width="1"/&gt;</description>
      <pubDate>19 Nov 2008</pubDate>
      <link>http://feedproxy.google.com/~r/purpleworkshops/~3/FwCEoCm3wrg/named-scope-refactored</link>
      <guid isPermaLink="false">http://www.purpleworkshops.com/articles/named-scope-refactored</guid>
      <dc:creator>Jeff Cohen</dc:creator>
    <feedburner:origLink>http://www.purpleworkshops.com/articles/named-scope-refactored</feedburner:origLink></item>
    <item>
      <title>Ruby 101: Method Definitions</title>
      <description>&lt;p&gt;&lt;i&gt;
        Note: For best formatting, you may want to &lt;a href="http://www.purpleworkshops.com/articles/method-definitions"&gt;view this article on the web&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Objects manage state, and they also exhibit behavior.  In this article, we'll be learning how to add behavior to classes that we write in Ruby.  
&lt;/p&gt;
&lt;p&gt;By "behavior" we mean, what the class, or an instance of the class, can "do."  While variables allow an object to store data, Ruby objects can define &lt;strong&gt;methods&lt;/strong&gt; that execute code.  This is an essential concept in object-oriented programming.  Objects don't just encapsulate data, they also perform actions and can have responsibilities assigned to them.
&lt;/p&gt;
&lt;h2&gt;1. The Basics&lt;/h2&gt;

&lt;p&gt;Sometimes the best way to learn is to dive right in.  Take a look at this Ruby code.
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Telephone&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;This Ruby code defines our &lt;code&gt;Telephone&lt;/code&gt; class.  A class is a blueprint for how to make objects of that class.  We can create a new &lt;code&gt;Telephone&lt;/code&gt; object by calling the &lt;code&gt;new&lt;/code&gt; method on our class:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="ident"&gt;my_phone&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Telephone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;&lt;code&gt;my_phone&lt;/code&gt; is now an &lt;strong&gt;instance&lt;/strong&gt; of a &lt;code&gt;Telephone&lt;/code&gt;.  What can our instance variable do that a plain &lt;code&gt;Object&lt;/code&gt; can't do? Well... nothing yet.  Let's teach a &lt;code&gt;Telephone&lt;/code&gt; how to dial a phone number:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5
6
7
8
9
10&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Telephone&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;dial&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;number&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dialing &lt;span class="expr"&gt;#{number}&lt;/span&gt;...&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;my_phone&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Telephone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;my_phone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dial&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1-800-555-1212&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;Here on line 3, we've defined an &lt;strong&gt;instance method&lt;/strong&gt; by using the &lt;strong&gt;def&lt;/strong&gt; keyword.  Save this code into a file named &lt;code&gt;phone.rb&lt;/code&gt;, and run it:
&lt;/p&gt;
&lt;pre class="session"&gt;c:\&gt; ruby phone.rb
Dialing 1-800-555-1212...
&lt;/pre&gt;

&lt;p&gt;We can define as many instance methods as we'd like.  Let's teach our object to hang up the phone.
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Telephone&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;dial&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;number&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dialing &lt;span class="expr"&gt;#{number}&lt;/span&gt;...&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;hang_up&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Hung up.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;my_phone&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Telephone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;my_phone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dial&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1-800-555-1212&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;my_phone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;hang_up&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;We'll get this:
&lt;/p&gt;
&lt;pre class="session"&gt;c:\&gt; ruby phone.rb
Dialing 1-800-555-1212...
Hung up.
&lt;/pre&gt;

&lt;p&gt;There is one special instance method you should know about, called the &lt;emph&gt;initializer&lt;/emph&gt;.  We don't have to define this method, but if we do, Ruby will call it for us automatically every time a new instance is created.  Here's an example:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Telephone&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;New telephone created!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;dial&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;number&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dialing &lt;span class="expr"&gt;#{number}&lt;/span&gt;...&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;hang_up&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Hung up.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;my_phone&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Telephone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;my_phone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dial&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1-800-555-1212&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;my_phone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;hang_up&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;Let's run it again:
&lt;/p&gt;
&lt;pre class="session"&gt;c:\&gt; ruby phone.rb
New telephone created!
Dialing 1-800-555-1212...
Hung up.
&lt;/pre&gt;

&lt;p&gt;Initializers can take arguments, just like our &lt;code&gt;dial&lt;/code&gt; method did.  We pass the actual argument values when we call &lt;code&gt;new&lt;/code&gt; to create instances of our object.  If we change our initializer to this:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;home_area_code&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;New telephone created!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="attribute"&gt;@area_code&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;home_area_code&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Our home area code is &lt;span class="expr"&gt;#{@area_code}&lt;/span&gt;.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;Now we are required to provide the phone's home area code when we construct a &lt;code&gt;Telephone&lt;/code&gt; instance:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="ident"&gt;my_phone&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Telephone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;312&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;And now we'll get output like this:
&lt;/p&gt;
&lt;pre class="session"&gt;c:\&gt; ruby phone.rb
New telephone created!
Our home area code is 312.
Dialing 1-800-555-1212...
Hung up.
&lt;/pre&gt;

&lt;h2&gt;Class Methods vs. Instance Methods&lt;/h2&gt;

&lt;div class="callout"&gt;&lt;img alt="Note" src="/images/icons/note.png?1247457308" /&gt;&lt;p&gt;
Java and C# &lt;emph&gt;static methods&lt;/emph&gt; are the same as &lt;emph&gt;class methods&lt;/emph&gt; in Ruby.
(Switching from .NET to Rails? &lt;a href="/book"&gt;Buy the book&lt;/a&gt;).
&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;So far we've learned how to create &lt;code&gt;instance methods&lt;/code&gt;.  They're called that because we have to first create an instance of our class before we can call them.
&lt;/p&gt;

&lt;p&gt;Sometimes we have functionality that seems appropriate to all telephones, regardless of _which_ telephone we might use.  We can create &lt;code&gt;class methods&lt;/code&gt; - methods that apply to the whole class, and not any specific instance.
&lt;/p&gt;

&lt;p&gt;Since all of our telephones have one thing in common - their manufacturer - we can create a class method to report the name of the manufacturer:
&lt;/p&gt;
              &lt;table class="code_listing"&gt;
                &lt;tr&gt;
                  &lt;td class="line_numbers"&gt;&lt;pre&gt;&lt;notextile&gt;1
2
3
4
5
6
7
8
9
10
11
12&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                  &lt;td class="code ruby"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Telephone&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.manufacturer&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Purple Telco&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="comment"&gt;# Rest of class definition goes here&lt;/span&gt;
  &lt;span class="comment"&gt;# ...&lt;/span&gt;
  
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="constant"&gt;Telephone&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;manufacturer&lt;/span&gt;
&lt;/notextile&gt;&lt;/pre&gt;&lt;/td&gt;
                &lt;/tr&gt;
              &lt;/table&gt;


&lt;p&gt;Notice how we prefix the &lt;code&gt;self&lt;/code&gt; keyword in front of the method name to indicate that it's a class method, instead of an instance method.  Let's run it:
&lt;/p&gt;
&lt;pre class="session"&gt;c:\&gt; ruby phone.rb
Purple Telco&lt;/pre&gt;

&lt;p&gt;Notice how we didn't need to create any instances first.  &lt;code&gt;manufacturer&lt;/code&gt; is a class method: all we needed was the name of the class.
&lt;/p&gt;
&lt;p&gt;Congratulations! You now know the basics of instance and class methods in Ruby.
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=ikLT40Y8FhA:fW_Sx_deL4E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=ikLT40Y8FhA:fW_Sx_deL4E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=ikLT40Y8FhA:fW_Sx_deL4E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=ikLT40Y8FhA:fW_Sx_deL4E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?i=ikLT40Y8FhA:fW_Sx_deL4E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/purpleworkshops?a=ikLT40Y8FhA:fW_Sx_deL4E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/purpleworkshops?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/purpleworkshops/~4/ikLT40Y8FhA" height="1" width="1"/&gt;</description>
      <pubDate>18 Nov 2008</pubDate>
      <link>http://feedproxy.google.com/~r/purpleworkshops/~3/ikLT40Y8FhA/method-definitions</link>
      <guid isPermaLink="false">http://www.purpleworkshops.com/articles/method-definitions</guid>
      <dc:creator>Jeff Cohen</dc:creator>
    <feedburner:origLink>http://www.purpleworkshops.com/articles/method-definitions</feedburner:origLink></item>
  </channel>
</rss>
