<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.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>acts_as_developer: Tag validation</title>
    <link>http://www.robertshowalter.com/articles/tag/validation</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Validating Mutually-Exclusive Attributes</title>
      <description>&lt;p&gt;Let&amp;#8217;s say you have a model that holds a location, with a &amp;#8220;state&amp;#8221; and a &amp;#8220;country&amp;#8221;. Suppose that you want the user to enter &lt;strong&gt;either&lt;/strong&gt; a state or a country, &lt;strong&gt;but not both&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Your first instinct might be to do something like this:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;validates_presence_of&lt;/span&gt; &lt;span class="symbol"&gt;:state&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:if&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;country&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;blank?&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;validates_presence_of&lt;/span&gt; &lt;span class="symbol"&gt;:country&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:if&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;state&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;blank?&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;That&amp;#8217;s not quite right however. You won&amp;#8217;t get an error if &lt;strong&gt;both&lt;/strong&gt; a state and a country are entered. Furthermore, if both attributes are entered, which one should be considered &amp;#8220;wrong&amp;#8221;?&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s where the generic &lt;code&gt;validate&lt;/code&gt; method can help. Rather than validating a specific attribute, &lt;code&gt;validate&lt;/code&gt; works on the whole row. If you need to add error messages you use the &lt;code&gt;ActiveRecord::Errors#add()&lt;/code&gt; and &lt;code&gt;#add_to_base()&lt;/code&gt; methods.&lt;/p&gt;


	&lt;p&gt;The validation for our state/country example looks like this:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;validate&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;row&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;state&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;blank?&lt;/span&gt; ^ &lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;country&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;blank?&lt;/span&gt;
    &lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;errors&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_to_base&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Either a state or a country is required (but not both)&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Note how &lt;code&gt;validate&lt;/code&gt; takes a block. The row being saved is passed to the block. The caret (&lt;code&gt;^&lt;/code&gt;) is Ruby&amp;#8217;s &amp;#8220;exclusive-or&amp;#8221; operator. It returns true only if exactly one of its operands is true, which fits our requirements perfectly.&lt;/p&gt;


	&lt;p&gt;The &lt;code&gt;add_to_base&lt;/code&gt; method adds an error message to the list of errors for the row, but the message is not specific to any single attribute. In this case, the error relates to two attributes, so I chose to use &lt;code&gt;add_to_base&lt;/code&gt;.&lt;/p&gt;</description>
      <pubDate>Sun, 16 Sep 2007 15:47:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:11ae682b-32dc-4f41-b07b-1d7c39e27bc5</guid>
      <author>Bob Showalter</author>
      <link>http://www.robertshowalter.com/articles/2007/09/16/validating-mutually-exclusive-attributes</link>
      <category>Rails</category>
      <category>validation</category>
    </item>
  </channel>
</rss>
