<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>ThiagoPradi.net</title>
  <link href="http://thiagopradi.net/atom.xml" rel="self"/>
  <link href="http://thiagopradi.net/"/>
  <updated>2012-01-19T01:26:43-02:00</updated>
  <id>http://thiagopradi.net/</id>
  <author>
    <name>Thiago Pradi</name>
    
      <email>thiago.pradi@gmail.com</email>
    
  </author>

  
  <entry>
    <title>Database Tip 1: Why Validate_uniqueness_of Is Broken</title>
    <link href="http://thiagopradi.net/blog/2012/01/19/why-validate-uniqueness-of-is-broken/"/>
    <updated>2012-01-19T00:56:00-02:00</updated>
    <id>http://thiagopradi.net/blog/2012/01/19/why-validate-uniqueness-of-is-broken</id>
    <content type="html">&lt;p&gt;This is a series of posts where I will be talking about some database tips for long time railers.&lt;/p&gt;

&lt;p&gt;In the past, I've been working on many rails projects, including big ones, that relies only on Rails validations for checking
all the Data Integrety before the model is saved in the Database.&lt;/p&gt;

&lt;p&gt;For most of validations, this makes sense. but validate_uniqueness_of is terrible broken, and could lead you to a number of problems.&lt;/p&gt;

&lt;p&gt;Imagine the following scenario:&lt;/p&gt;

&lt;p&gt;You have your model user, which have a unique e-mail, like this:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;n&quot;&gt;validate_presence_of&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;n&quot;&gt;validate_uniqueness_of&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;So, in your production environment, you have configured to use unicorn + ngnix, with 4 workers.&lt;/p&gt;

&lt;p&gt;In your production environment, the user creating is wrapped into a transaction with more business logic. So, here is the problem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Worker 1 starts a user creation trasaction&lt;/li&gt;
&lt;li&gt;Worker 2 starts a user creation trasaction&lt;/li&gt;
&lt;li&gt;Worker 1 makes the query to see if this e-mail is already taken, which return false, because the user wasn't persisted in the database yet.&lt;/li&gt;
&lt;li&gt;Worker 2 makes the query to see if this e-mail is already taken, which return false, because the user wasn't persisted in the database yet.&lt;/li&gt;
&lt;li&gt;Worker 1 finish the transaction, inserting the user.&lt;/li&gt;
&lt;li&gt;Worker 2 finishes the trasaction, inserting a user with duplicated e-mail.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;This could be easily solved using a unique index in the database, which raises a exception if a duplicated data is entered.
The index could be created in a migration, using the following code:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class=&quot;n&quot;&gt;add_index&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;For more about unique indexes, check this article: &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/create-index.html&quot;&gt;Mysql Unique Indexes&lt;/a&gt; and this &lt;a href=&quot;http://www.postgresql.org/docs/9.0/static/indexes-unique.html&quot;&gt;PostgreSQL Unique indexes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Protip: be nice to your users, and rescue from the exception when this occurs, putting a nice message, like the following code:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UsersController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;c1&quot;&gt;# do user stuff&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;StatementInvalid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;n&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Something bad happens&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_user_path&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>New Blog</title>
    <link href="http://thiagopradi.net/blog/2011/08/28/new-blog-new-life/"/>
    <updated>2011-08-28T22:28:00-03:00</updated>
    <id>http://thiagopradi.net/blog/2011/08/28/new-blog-new-life</id>
    <content type="html">&lt;p&gt;Hi Guys! This is my first post using my new blog engine. This blog is powered by &lt;a href=&quot;http://http://octopress.org//&quot;&gt;Octopress&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some events that happenned this year gave me some extra motivation to start writing again,
like getting my english skills on track again (it's so worst now) and experiences in my new job / college.&lt;/p&gt;

&lt;p&gt;Hope you guys like it!&lt;/p&gt;

&lt;p&gt;Thanks,&lt;/p&gt;

&lt;p&gt;Thiago&lt;/p&gt;
</content>
  </entry>
  
</feed>

