<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Robby on Rails: Using Named Placeholders in Ruby</title>
    <link>http://www.robbyonrails.com/articles/2005/10/21/using-named-placeholders-in-ruby</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>thoughts.sort_by{|t| t[:topic]}.collect </description>
    <item>
      <title>Using Named Placeholders in Ruby</title>
      <description>&lt;p&gt;&lt;strong&gt;Insert Hip Quote Here:&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&amp;#8220;In ancient times, hundreds of years before the dawn of history, an ancient race of people&amp;#8230; the Druids. No one knows who they were or what they were doing&amp;#8230; &amp;#8220;&lt;/em&gt; &amp;#8211; Nigel Tufnel, Spinal Tap&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Story Time&amp;#8230;&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Earlier, I was giving a customer of ours, Jared from &lt;a href="http://www.communitywalk.com"&gt;CommunityWalk.com&lt;/a&gt; a quick tutorial on some of the features script/console&amp;#8230; which lead to helping him with a &lt;span class="caps"&gt;SQL&lt;/span&gt; query. When I provided him with some working code he was curious about what I had done in the &lt;span class="caps"&gt;SQL&lt;/span&gt; query string that I was passing to &lt;code&gt;find_by_sql&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;WARNING&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;If you have &lt;span class="caps"&gt;ANY SQL&lt;/span&gt; queries that resembles the following, &lt;span class="caps"&gt;PLEASE READ THE REST OF THIS&lt;/span&gt;. :-)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:search&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
&lt;span class="constant"&gt;RockLegend&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:conditions&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;first_name = '&lt;span class="expr"&gt;#{values['first_name']}&lt;/span&gt;'&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;If you are doing that&amp;#8230; then you are opening yourself up to some security problems. Let&amp;#8217;s take a few minutes and discuss how you can make this more secure and still keep your code readable. (the best of both worlds!)&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;The ? Placeholder&lt;/strong&gt;&lt;/p&gt;


Many of you are probably familiar with this approach&amp;#8230;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;RockLegend&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:conditions&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;first_name = ?&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Nigel&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="constant"&gt;RockLegend&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:conditions&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;first_name = ? AND last_name = ?&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Nigel&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tufnel&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;You can pass it a hash as well.. and as long as you put everything in the same order as the &lt;code&gt;?&lt;/code&gt;s are placed&amp;#8230; then all is well.&lt;/p&gt;


	&lt;p&gt;My only real problem with this approach is that it requires you to keep things in a specific sequential order&amp;#8230; and who wants to keep track of that? So, I would like to recommend that you use named placeholders. Aside from that, it looks magical and I don&amp;#8217;t like magical-looking code. I like &lt;em&gt;easy to read code&lt;/em&gt;. :-)&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Named Placeholders&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;If you already use these&amp;#8230; you know how  useful they can be in your &lt;span class="caps"&gt;SQL&lt;/span&gt; queries. If you haven&amp;#8217;t seen them before&amp;#8230; it&amp;#8217;s because the Rails docs don&amp;#8217;t really mention it and is something that comes from the underlying database library in Ruby. So what is so great about these?&lt;/p&gt;


Let&amp;#8217;s first replace the above code with named parameters&amp;#8230;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;RockLegend&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:conditions&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;first_name = :first_name&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:first_name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Nigel&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;We are passing a hash with a matching key to the conditions option. Pretty neat, right? In this case with just one placeholder we just increased the amount of code to do the same thing. So, it might always be the best solution&amp;#8230; but it is &lt;em&gt;easier to read&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s try another with multiple keys in our hash&amp;#8230; infact, we&amp;#8217;ll build the hash prior to calling &lt;code&gt;find&lt;/code&gt;.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:first_name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Nigel&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:last_name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tufnel&lt;/span&gt;&lt;span class="punct"&gt;'}&lt;/span&gt;
&lt;span class="constant"&gt;RockLegend&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:conditions&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;first_name = :first_name AND last_name = :last_name&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;It will happily match the hash keys to the named placeholders in the conditions string. Again, nothing terribly exciting&amp;#8230;but it is &lt;em&gt;easier to read&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Who cares about order? Not named placeholders!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Okay, let&amp;#8217;s mix things up a bit&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:last_name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tufnel&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:first_name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Nigel&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="constant"&gt;RockLegend&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:conditions&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;first_name = :first_name AND last_name = :last_name&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The hash keys were not added in the same order&amp;#8230; but it still works!&lt;/p&gt;


	&lt;p&gt;Okay, now for one last quick example (it&amp;#8217;s late and I am tired&amp;#8230;).&lt;/p&gt;


	&lt;p&gt;I have a search mechanism on a site that allows you to search for a string of text across multiple fields. So, I have one string&amp;#8230; but several fields to compare against.&lt;/p&gt;


Here is a string that I will pass to the &lt;code&gt;find&lt;/code&gt; method.
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;conditions&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;role = :role AND (first_name ~* :str OR last_name ~* :str OR nick_name ~* :str)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this string is using &lt;a href="http://rubyurl.com/DYE"&gt;PostgreSQL regular expressions&lt;/a&gt;... (&lt;code&gt;~*&lt;/code&gt;).&lt;/p&gt;


	&lt;p&gt;Here is a hash that with that matches the keys, &lt;code&gt;:str&lt;/code&gt; and &lt;code&gt;:role&lt;/code&gt;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:str&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^(Nigel|Tufnel)$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:role&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Guitar&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;If you look above, you&amp;#8217;ll see that the &lt;code&gt;conditions&lt;/code&gt; string contains &lt;strong&gt;four&lt;/strong&gt; named placeholders&amp;#8230; but the hash only has &lt;strong&gt;two&lt;/strong&gt; keys. With the &lt;code&gt;?&lt;/code&gt; placeholder, we would have to pass the same vaule three times&amp;#8230; which isn&amp;#8217;t any fun to read or maintain. ;-/&lt;/p&gt;


	&lt;p&gt;So, with our new friends, &lt;strong&gt;named parameters&lt;/strong&gt;, we can call &lt;code&gt;find&lt;/code&gt; (or any find-like method) using this technique for placeholders.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;RockLegend&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:conditions&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt; &lt;span class="ident"&gt;conditions&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;...and hopefully this is useful to you.  :-)&lt;/p&gt;


	&lt;p&gt;Have fun!&lt;/p&gt;
</description>
      <pubDate>Fri, 21 Oct 2005 00:53:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:4ffd337b75c41f3b73433e7919ddca5e</guid>
      <author>Robby Russell</author>
      <link>http://www.robbyonrails.com/articles/2005/10/21/using-named-placeholders-in-ruby</link>
      <category>Ruby on Rails</category>
      <category>Ruby</category>
      <category>Programming</category>
      <category>PostgreSQL</category>
      <category>activerecord</category>
      <category>rails</category>
      <category>ruby</category>
      <category>postgresql</category>
    </item>
    <item>
      <title>"Using Named Placeholders in Ruby" by Sokolov Yura</title>
      <description>&lt;p&gt;Wow. Thanks.&lt;/p&gt;</description>
      <pubDate>Sun, 27 Aug 2006 03:34:26 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:bd472e06-8002-425e-b173-5c4c946c91d6</guid>
      <link>http://www.robbyonrails.com/articles/2005/10/21/using-named-placeholders-in-ruby#comment-21873</link>
    </item>
    <item>
      <title>"Using Named Placeholders in Ruby" by Ben Reubenstein</title>
      <description>&lt;p&gt;Great post.  Very useful!  Thank you.&lt;/p&gt;</description>
      <pubDate>Fri, 25 Aug 2006 15:45:38 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:16b1a89d-83fe-4210-8f74-6bfbd5f16e41</guid>
      <link>http://www.robbyonrails.com/articles/2005/10/21/using-named-placeholders-in-ruby#comment-21866</link>
    </item>
  </channel>
</rss>
