<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ruby on rails on random thoughts</title><link>https://awesomeprogrammer.com/categories/ruby-on-rails/</link><description>Recent content in ruby on rails on random thoughts</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Wed, 25 Sep 2013 00:00:00 +0000</lastBuildDate><atom:link href="https://awesomeprogrammer.com/categories/ruby-on-rails/index.xml" rel="self" type="application/rss+xml"/><item><title>Rails after_commit create mindf*ck</title><link>https://awesomeprogrammer.com/blog/2013/09/25/rails-after-commit-create-mindf-star-ck/</link><pubDate>Wed, 25 Sep 2013 00:00:00 +0000</pubDate><guid>https://awesomeprogrammer.com/blog/2013/09/25/rails-after-commit-create-mindf-star-ck/</guid><description><![CDATA[<p>Rails 3 observers can be tricky. You probably already heard a thousand times how to deal with <em>undefined</em> id issue and how transactions are handled, so let&rsquo;s take a quick example that can be google&rsquo;d in just a couple of seconds.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserObserver</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Observer</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">after_commit</span>(user)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">unless</span> user<span style="color:#f92672">.</span>send(<span style="color:#e6db74">:transaction_include_action?</span>, <span style="color:#e6db74">:create</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># some code that should be executed only on create, after transaction is committed</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>So what&rsquo;s wrong with this example? Nothing. But let say <code>SuperUser</code> <em>has_many</em> <code>users</code>. Some example code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SuperUser</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Base</span>
</span></span><span style="display:flex;"><span>  has_many <span style="color:#e6db74">:users</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">User</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Base</span>
</span></span><span style="display:flex;"><span>  attr_accessible <span style="color:#e6db74">:name</span>
</span></span><span style="display:flex;"><span>  validates <span style="color:#e6db74">:name</span>, <span style="color:#e6db74">presence</span>: <span style="color:#66d9ef">true</span>, <span style="color:#e6db74">inclusion</span>: { <span style="color:#66d9ef">in</span>: <span style="color:#e6db74">%(foo bar)</span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserObserver</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Observer</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">after_commit</span>(user)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">unless</span> user<span style="color:#f92672">.</span>send(<span style="color:#e6db74">:transaction_include_action?</span>, <span style="color:#e6db74">:create</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">raise</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">#{</span>user<span style="color:#f92672">.</span>inspect<span style="color:#e6db74">}</span><span style="color:#e6db74"> | Persisted: </span><span style="color:#e6db74">#{</span>user<span style="color:#f92672">.</span>persisted?<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>And try it out:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#75715e"># obviously we need super user first</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">SuperUser</span><span style="color:#f92672">.</span>first<span style="color:#f92672">.</span>users<span style="color:#f92672">.</span>create(name: <span style="color:#e6db74">&#34;boo&#34;</span>) <span style="color:#75715e"># this won&#39;t create record, due validation</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#&lt;RuntimeError: #&lt;User id: nil, name: &#34;boo&#34;, owner_id: 1, created_at: nil, updated_at: nil&gt; | Persisted: false&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">=&gt;</span> <span style="color:#75715e">#&lt;User id: nil, name: &#34;boo&#34;, owner_id: 1, created_at: nil, updated_at: nil&gt;</span>
</span></span></code></pre></div><p>Hell yeah, observer code executed perfectly, even this is not what we would normally expect. I was quite surprised with this behavior, I recommend checking out <a href="https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/transactions.rb">ActiveRecord::Transactions</a> internals, if I find some time I will write a follow-up to this, cheers.</p>]]></description><content:encoded><![CDATA[<p>Rails 3 observers can be tricky. You probably already heard a thousand times how to deal with <em>undefined</em> id issue and how transactions are handled, so let&rsquo;s take a quick example that can be google&rsquo;d in just a couple of seconds.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserObserver</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Observer</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">after_commit</span>(user)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">unless</span> user<span style="color:#f92672">.</span>send(<span style="color:#e6db74">:transaction_include_action?</span>, <span style="color:#e6db74">:create</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># some code that should be executed only on create, after transaction is committed</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>So what&rsquo;s wrong with this example? Nothing. But let say <code>SuperUser</code> <em>has_many</em> <code>users</code>. Some example code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SuperUser</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Base</span>
</span></span><span style="display:flex;"><span>  has_many <span style="color:#e6db74">:users</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">User</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Base</span>
</span></span><span style="display:flex;"><span>  attr_accessible <span style="color:#e6db74">:name</span>
</span></span><span style="display:flex;"><span>  validates <span style="color:#e6db74">:name</span>, <span style="color:#e6db74">presence</span>: <span style="color:#66d9ef">true</span>, <span style="color:#e6db74">inclusion</span>: { <span style="color:#66d9ef">in</span>: <span style="color:#e6db74">%(foo bar)</span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserObserver</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ActiveRecord</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Observer</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">after_commit</span>(user)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">unless</span> user<span style="color:#f92672">.</span>send(<span style="color:#e6db74">:transaction_include_action?</span>, <span style="color:#e6db74">:create</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">raise</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">#{</span>user<span style="color:#f92672">.</span>inspect<span style="color:#e6db74">}</span><span style="color:#e6db74"> | Persisted: </span><span style="color:#e6db74">#{</span>user<span style="color:#f92672">.</span>persisted?<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>And try it out:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#75715e"># obviously we need super user first</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">SuperUser</span><span style="color:#f92672">.</span>first<span style="color:#f92672">.</span>users<span style="color:#f92672">.</span>create(name: <span style="color:#e6db74">&#34;boo&#34;</span>) <span style="color:#75715e"># this won&#39;t create record, due validation</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#&lt;RuntimeError: #&lt;User id: nil, name: &#34;boo&#34;, owner_id: 1, created_at: nil, updated_at: nil&gt; | Persisted: false&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">=&gt;</span> <span style="color:#75715e">#&lt;User id: nil, name: &#34;boo&#34;, owner_id: 1, created_at: nil, updated_at: nil&gt;</span>
</span></span></code></pre></div><p>Hell yeah, observer code executed perfectly, even this is not what we would normally expect. I was quite surprised with this behavior, I recommend checking out <a href="https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/transactions.rb">ActiveRecord::Transactions</a> internals, if I find some time I will write a follow-up to this, cheers.</p>]]></content:encoded></item></channel></rss>