<?xml version="1.0" encoding="UTF-8"?>
<rss version='2.0' xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>John Bachir&#39;s Code Blog</title>
    <description></description>
    <link>https://jjbcode.silvrback.com/feed</link>
    <atom:link href="https://jjbcode.silvrback.com/feed" rel="self" type="application/rss+xml"/>
    <category domain="jjbcode.silvrback.com">Content Management/Blog</category>
    <language>en-us</language>
      <pubDate>Mon, 17 Oct 2022 22:35:47 -0400</pubDate>
    <managingEditor>j-code@jjb.cc (John Bachir&#39;s Code Blog)</managingEditor>
      <item>
        <guid>http://code.jjb.cc/how-expensive-is-it-to-create-procs-and-lambdas-in-ruby#54185</guid>
          <pubDate>Mon, 17 Oct 2022 22:35:47 -0400</pubDate>
        <link>http://code.jjb.cc/how-expensive-is-it-to-create-procs-and-lambdas-in-ruby</link>
        <title>How expensive is it to create Procs and lambdas in ruby?</title>
        <description>(answer: not expensive)</description>
        <content:encoded><![CDATA[<p>I recently implemented <a href="https://github.com/jjb/ruby-clock#callbacks">fancier around callbacks for ruby-clock</a>. To do this sort of thing, you need to generate a Proc or lambda on the fly, so that each subsequent callback has something to <code>.call</code>. Procs and lambdas can&#39;t accept a block, so that&#39;s the only way to do it. Which is also a bit educational because you sort of end up implementing blocks in the process.</p>

<p>I&#39;m fairly certain this is the only way. <a href="https://github.com/jjb/ruby-clock/pull/23/files#diff-9a8c12fe5d35df3b736c20674f0bc9deaf97e6686eec0a9402628553f1b746c2R131-R142">Here&#39;s how I did it</a>. <a href="https://github.com/rails/rails/blob/main/activesupport/lib/active_support/callbacks.rb#L95">Here&#39;s how rails does it</a>, although I admit I did not invest time into understanding this code.</p>

<p>After successfully implementing this I got curious if there were any performance concerns with generating Procs. So here&#39;s a simple benchmark, testing how much overhead there is to create and invoke Procs and lambdas:</p>
<div class="highlight"><pre><span></span><span class="n">t</span> <span class="o">=</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span>
<span class="mi">10_000_000</span><span class="o">.</span><span class="n">times</span> <span class="p">{</span><span class="mi">1</span><span class="o">+</span><span class="mi">1</span><span class="p">}</span>
<span class="nb">puts</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">t</span>

<span class="n">t</span> <span class="o">=</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span>
<span class="mi">10_000_000</span><span class="o">.</span><span class="n">times</span> <span class="p">{</span><span class="nb">lambda</span><span class="p">{</span><span class="mi">1</span><span class="o">+</span><span class="mi">1</span><span class="p">}</span><span class="o">.</span><span class="n">call</span><span class="p">}</span>
<span class="nb">puts</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">t</span>

<span class="n">t</span> <span class="o">=</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span>
<span class="mi">10_000_000</span><span class="o">.</span><span class="n">times</span> <span class="p">{</span><span class="no">Proc</span><span class="o">.</span><span class="n">new</span><span class="p">{</span> <span class="mi">1</span><span class="o">+</span><span class="mi">1</span> <span class="p">}</span><span class="o">.</span><span class="n">call</span><span class="p">}</span>
<span class="nb">puts</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">t</span>
</pre></div><div class="highlight"><pre><span></span>0.206395
1.670558
1.915812
</pre></div>
<p>(I was too lazy to use the benchmark library, do a warmup, etc. but I did do a quick check with putting them in a different order and the results were identical.)</p>

<p>So there you have it - don&#39;t worry about the overhead of using Procs and lambdas.</p>

<p>Looks like lambdas are slightly more performant than Procs. I went with Procs because I think of them as &quot;a block turned into an object&quot;, and that&#39;s the vibe here. I didn&#39;t think this through at the time. but I think I also prefer the Proc behavior of a <code>return</code> taking over the calling context. This maybe gives the opportunity for an around hook to halt progress (e.g. an around hook which sometimes decide that a job shouldn&#39;t run at all). I&#39;ll experiment with this eventually and maybe document it as a feature.</p>
]]></content:encoded>
      </item>
      <item>
        <guid>http://code.jjb.cc/benchmarking-various-methods-of-accumulating-a-unique-set-in-ruby#53864</guid>
          <pubDate>Sun, 24 Jul 2022 19:17:59 -0400</pubDate>
        <link>http://code.jjb.cc/benchmarking-various-methods-of-accumulating-a-unique-set-in-ruby</link>
        <title>Benchmarking various methods of accumulating a set / unique array in ruby</title>
        <description></description>
        <content:encoded><![CDATA[<p>I recently benchmarked a few ways to accumulate a set in ruby. Here are my findings and methodology - apologies for messiness, I&#39;m just sharing what I came up.</p>

<p>This is with ruby 3.1. I also ran under 2.7, I believe the set case was actually faster, but I may be misremembering.</p>

<h2 id="results">Results</h2>

<h3 id="time">Time</h3>
<div class="highlight"><pre><span></span>                      user     system      total        real
set               0.095938   0.000404   0.096342 (  0.096341)
array after       0.063998   0.002452   0.066450 (  0.066508)
array in place   17.238500   0.939414  18.177914 ( 18.188532)
</pre></div>
<h3 id="memory-allocations">Memory Allocations</h3>
<div class="highlight"><pre><span></span>                 set    28.848k memsize (     0.000  retained)
                         3.000  objects (     0.000  retained)
                         0.000  strings (     0.000  retained)
         array after     8.040k memsize (     0.000  retained)
                         1.000  objects (     0.000  retained)
                         0.000  strings (     0.000  retained)
      array in place     8.072B memsize (     0.000  retained)
                         2.000M objects (     0.000  retained)
                         0.000  strings (     0.000  retained)

Comparison:
         array after:       8040 allocated
                 set:      28848 allocated - 3.59x more
      array in place: 8071798800 allocated - 1003955.07x more
</pre></div>
<h3 id="process-memory">Process Memory</h3>
<div class="highlight"><pre><span></span>array_after
before (base): 42.95
memory above base:
  largest during iteration: 869.63
  average during iteration: 433.52
  after final array is produced: 877.47

set
before (base): 43.41
memory above base:
  largest during iteration: 865.65
  average during iteration: 432.5
  after final array is produced: 865.65

array_in_place
before (base): 42.98
memory above base:
  largest during iteration: 3312.82
  average during iteration: 1546.41
  after final array is produced: 593.1
</pre></div>
<h2 id="discussion">Discussion</h2>

<h3 id="time">Time</h3>

<p>Array in place is very very slow, the others are very fast and in practice probably identical for most workloads, with array unique being the fastest, perhaps because it does less redundant work, at the expense of memory usage.</p>

<h3 id="memory-allocations">Memory Allocations</h3>

<p>Array in place allocates 1 million times more objects than set because it needs to create the wrapper&quot; array for each element. In practice the total impact on process memory would not be this much because GC would frequently run (which adds cost and is an additional reason this is a bad solution).</p>

<p>Set uses 3.6x more allocations than array after, I don&#39;t have a theory why, didn&#39;t look at the code.</p>

<h3 id="process-memory">Process Memory</h3>

<p>I tried a variety of things but wasn&#39;t able to get consistent or sensible results out of this. Lack of control of the ruby memory allocator made it difficult. Hopefully allocations measurement above is sufficient to compare memory use.</p>

<h2 id="conclusions">Conclusions</h2>

<p>array_after is the most common approach and is also the fastest and is probably Fine for most applications.</p>

<p>Set uses more total memory AND is slower than array_after. This does not make sense to me, I would have expected memory to be lower. Maybe benchmark-memory doesn&#39;t actually provide peak memory?</p>

<p>array_in_place uses the most memory and is also the slowest.</p>

<p>Of course array_after might use much much more memory than array_in_place depending on the data / application. (if building up a 100megabyte array and then after <code>uniq!</code> it&#39;s only 0.1 megabyte, then it&#39;s using much more memory in the loop than it ultimately needs).</p>

<h2 id="code">Code</h2>
<div class="highlight"><pre><span></span><span class="nb">require</span> <span class="s1">&#39;set&#39;</span>

<span class="c1"># so we can control when GC happens, which I believe is:</span>
<span class="c1">#  - valuable for the time measurements being more consistent, and realistic for a post-warmup app</span>
<span class="c1">#  - irrelevant for the allocations measurements</span>
<span class="c1">#  - chaotic for the process memory measurements</span>
<span class="no">GC</span><span class="o">.</span><span class="n">disable</span>

<span class="vi">@data</span> <span class="o">=</span> <span class="o">[]</span>
<span class="mi">1_000_000</span><span class="o">.</span><span class="n">times</span><span class="p">{</span> <span class="vi">@data</span> <span class="o">&lt;&lt;</span> <span class="nb">rand</span><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">1_000</span><span class="p">)</span> <span class="p">}</span>

<span class="c1"># Things we are not able to measure</span>
<span class="c1"># - average and max memory or allocation usage while uniq! is running</span>
<span class="c1"># - average and max memory or allocation usage while |= [d] or &lt;&lt; d are happening (hopefully woudn&#39;t change conclusions... but maybe!?)</span>
<span class="c1"># - while @s.to_a is happening</span>

<span class="c1">############################</span>
<span class="c1"># The Three Implementations</span>
<span class="c1">#</span>
<span class="c1"># each ends with nil because without that, benchmark showed slight variations</span>
<span class="c1"># in certain scenarios when not expected (such as whether or not doing to_a at end of set)</span>
<span class="c1"># i&#39;m guessing because under the hood benchmark is doing somethign with the return result, such as</span>
<span class="c1"># inspect</span>
<span class="c1">############################</span>

<span class="c1"># Typical simple implementation: build up an array, then call uniq on it afterward</span>
<span class="k">def</span> <span class="nf">array_after</span>
  <span class="n">a2</span> <span class="o">=</span> <span class="o">[]</span>
  <span class="vi">@data</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">d</span><span class="o">|</span>
    <span class="k">yield</span> <span class="k">if</span> <span class="nb">block_given?</span>
    <span class="n">a2</span> <span class="o">&lt;&lt;</span> <span class="n">d</span>
  <span class="k">end</span>
  <span class="n">a2</span><span class="o">.</span><span class="n">uniq!</span>
  <span class="kp">nil</span>
<span class="k">end</span>

<span class="c1"># Build in Array, unique on each iteration</span>
<span class="c1"># Array elements remain unique on each iteration, theoretically has</span>
<span class="c1"># total memory benefits over uniqueing after. But, cost of creating an Array on each iteration comes into play.</span>
<span class="k">def</span> <span class="nf">array_in_place</span>
  <span class="n">a</span> <span class="o">=</span> <span class="o">[]</span>
  <span class="vi">@data</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">d</span><span class="o">|</span>
    <span class="k">yield</span> <span class="k">if</span> <span class="nb">block_given?</span>
    <span class="n">a</span> <span class="o">|=</span> <span class="o">[</span><span class="n">d</span><span class="o">]</span>
  <span class="k">end</span>
  <span class="kp">nil</span>
<span class="k">end</span>

<span class="c1"># Use Set, which is made for just this purpose</span>
<span class="k">def</span> <span class="nf">set</span>
  <span class="n">s</span> <span class="o">=</span> <span class="no">Set</span><span class="o">.</span><span class="n">new</span>
  <span class="vi">@data</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">d</span><span class="o">|</span>
    <span class="k">yield</span> <span class="k">if</span> <span class="nb">block_given?</span>
    <span class="n">s</span> <span class="o">&lt;&lt;</span> <span class="n">d</span>
  <span class="k">end</span>
  <span class="n">set_a</span> <span class="o">=</span> <span class="vi">@s</span><span class="o">.</span><span class="n">to_a</span>
  <span class="kp">nil</span>
<span class="k">end</span>

<span class="c1">#######</span>
<span class="c1"># Time</span>
<span class="c1">#######</span>
<span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">Time&quot;</span>
<span class="nb">require</span> <span class="s1">&#39;benchmark&#39;</span>
<span class="mi">5</span><span class="o">.</span><span class="n">times</span><span class="p">{</span><span class="no">GC</span><span class="o">.</span><span class="n">compact</span><span class="p">}</span>

<span class="no">Benchmark</span><span class="o">.</span><span class="n">bmbm</span><span class="p">(</span><span class="mi">15</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
  <span class="n">x</span><span class="o">.</span><span class="n">report</span><span class="p">(</span><span class="s2">&quot;set&quot;</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">set</span>
  <span class="k">end</span>

  <span class="n">x</span><span class="o">.</span><span class="n">report</span><span class="p">(</span><span class="s2">&quot;array after&quot;</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">array_after</span>
  <span class="k">end</span>

  <span class="n">x</span><span class="o">.</span><span class="n">report</span><span class="p">(</span><span class="s2">&quot;array in place&quot;</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">array_in_place</span>
  <span class="k">end</span>
<span class="k">end</span>


<span class="c1">#####################</span>
<span class="c1"># Memory Allocations</span>
<span class="c1">#####################</span>
<span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">Memory Allocations&quot;</span>
<span class="no">GC</span><span class="o">.</span><span class="n">enable</span>
<span class="nb">require</span> <span class="s1">&#39;benchmark-memory&#39;</span>
<span class="no">GC</span><span class="o">.</span><span class="n">disable</span>
<span class="mi">5</span><span class="o">.</span><span class="n">times</span><span class="p">{</span><span class="no">GC</span><span class="o">.</span><span class="n">compact</span><span class="p">}</span>
<span class="no">Benchmark</span><span class="o">.</span><span class="n">memory</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
  <span class="n">x</span><span class="o">.</span><span class="n">compare!</span>

  <span class="n">x</span><span class="o">.</span><span class="n">report</span><span class="p">(</span><span class="s2">&quot;set&quot;</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">set</span>
  <span class="k">end</span>

  <span class="n">x</span><span class="o">.</span><span class="n">report</span><span class="p">(</span><span class="s2">&quot;array after&quot;</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">array_after</span>
  <span class="k">end</span>

  <span class="n">x</span><span class="o">.</span><span class="n">report</span><span class="p">(</span><span class="s2">&quot;array in place&quot;</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">array_in_place</span>
  <span class="k">end</span>
<span class="k">end</span> <span class="k">if</span> <span class="kp">false</span>

<span class="nb">exit</span>

<span class="c1">#################</span>
<span class="c1"># Process Memory</span>
<span class="c1"># To run these, i disabled all above tests, and only ran one at a time, sometimes with</span>
<span class="c1"># RUBY_GC_HEAP_GROWTH_FACTOR=1.1 ruby benchmark.rb</span>
<span class="c1">#################</span>
<span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">Process Memory&quot;</span>

<span class="k">def</span> <span class="nf">print_mem_stats</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
  <span class="n">mem</span> <span class="o">=</span> <span class="no">GetProcessMem</span><span class="o">.</span><span class="n">new</span>
  <span class="n">mem_samples</span> <span class="o">=</span> <span class="o">[]</span>
  <span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="si">#{</span><span class="n">m</span><span class="si">}</span><span class="s2">&quot;</span>

  <span class="mi">5</span><span class="o">.</span><span class="n">times</span><span class="p">{</span><span class="no">GC</span><span class="o">.</span><span class="n">compact</span><span class="p">}</span>

  <span class="n">base</span> <span class="o">=</span> <span class="n">mem</span><span class="o">.</span><span class="n">mb</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
  <span class="nb">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">m</span><span class="p">){</span> <span class="n">mem_samples</span> <span class="o">&lt;&lt;</span> <span class="n">mem</span><span class="o">.</span><span class="n">mb</span> <span class="p">}</span>
  <span class="n">after</span> <span class="o">=</span> <span class="n">mem</span><span class="o">.</span><span class="n">mb</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>

  <span class="nb">puts</span> <span class="s2">&quot;before (base): </span><span class="si">#{</span><span class="n">base</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="nb">puts</span> <span class="s2">&quot;memory above base:&quot;</span>
  <span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\t</span><span class="s2">largest during iteration: </span><span class="si">#{</span><span class="p">(</span><span class="n">mem_samples</span><span class="o">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">base</span><span class="p">)</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\t</span><span class="s2">average during iteration: </span><span class="si">#{</span><span class="p">((</span><span class="n">mem_samples</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">/</span> <span class="n">mem_samples</span><span class="o">.</span><span class="n">size</span><span class="p">)</span> <span class="o">-</span> <span class="n">base</span><span class="p">)</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\t</span><span class="s2">after final array is produced: </span><span class="si">#{</span><span class="p">(</span><span class="n">after</span> <span class="o">-</span> <span class="n">base</span><span class="p">)</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="k">end</span>

<span class="nb">require</span> <span class="s1">&#39;get_process_mem&#39;</span>
<span class="mi">5</span><span class="o">.</span><span class="n">times</span><span class="p">{</span><span class="no">GC</span><span class="o">.</span><span class="n">compact</span><span class="p">}</span>

<span class="n">print_mem_stats</span><span class="p">(</span><span class="ss">:array_after</span><span class="p">)</span>
<span class="n">print_mem_stats</span><span class="p">(</span><span class="ss">:set</span><span class="p">)</span>
<span class="n">print_mem_stats</span><span class="p">(</span><span class="ss">:array_in_place</span><span class="p">)</span>

<span class="nb">puts</span> <span class="vi">@data</span><span class="o">.</span><span class="n">count</span> <span class="c1"># to trick GC into not thinking it&#39;s done, so that &quot;after above base&quot; comparison is more meaningful</span>
<span class="c1"># 5.times{GC.compact}</span>
<span class="c1"># puts &quot;cleaned up: #{@mem.mb.round(2)}&quot;</span>
<span class="c1"># puts &quot;equal? #{@set_a.sort == @a.sort &amp;&amp; @a.sort == @a2.sort}&quot;</span>
</pre></div>]]></content:encoded>
      </item>
      <item>
        <guid>http://code.jjb.cc/you-can-t-declare-after_-_commit-or-after_commit-callbacks-for-the-same-method-more-than-once#53332</guid>
          <pubDate>Fri, 25 Feb 2022 21:58:27 -0500</pubDate>
        <link>http://code.jjb.cc/you-can-t-declare-after_-_commit-or-after_commit-callbacks-for-the-same-method-more-than-once</link>
        <title>You can&#39;t declare after_*_commit or after_commit callbacks for the same method more than once!</title>
        <description>wow.</description>
        <content:encoded><![CDATA[<p>In Rails ActiveRecord, I just discovered that if you do this:</p>
<div class="highlight"><pre><span></span><span class="c1"># bad code!</span>
<span class="n">after_update_commit</span> <span class="ss">:thing</span>
<span class="n">after_create_commit</span> <span class="ss">:thing</span>
</pre></div>
<p>Only the second one will take effect! After <a href="https://rubyonrails-link.slack.com/archives/C05054QPL/p1645841001998229">asking in the rails slack</a>, I was pointed to <a href="https://guides.rubyonrails.org/active_record_callbacks.html#transaction-callbacks">the docs</a> which actually cover this:</p>

<blockquote>
<p>Using both after_create_commit and after_update_commit with the same method name will only allow the last callback defined to take effect, as they both internally alias to after_commit which overrides previously defined callbacks with the same method name.</p>
</blockquote>

<p>To me, the docs are ambiguous about if &quot;which overrides&quot; refers to the aliasing or to the behavior of <code>after_commit</code>. Sadly, it&#39;s the latter. This has the same problem:</p>
<div class="highlight"><pre><span></span><span class="c1"># bad code!</span>
<span class="n">after_commit</span> <span class="ss">:thing</span><span class="p">,</span> <span class="ss">on</span><span class="p">:</span> <span class="ss">:update</span>
<span class="n">after_commit</span> <span class="ss">:thing</span><span class="p">,</span> <span class="ss">on</span><span class="p">:</span> <span class="ss">:create</span>
</pre></div>
<p>In my examples above, the problem can be easily solved with</p>
<div class="highlight"><pre><span></span><span class="n">after_commit</span> <span class="ss">:thing</span><span class="p">,</span> <span class="ss">on</span><span class="p">:</span> <span class="o">[</span><span class="ss">:update</span><span class="p">,</span> <span class="ss">:create</span><span class="o">]</span>
</pre></div>
<p>But it&#39;s trickier if you have conditions</p>
<div class="highlight"><pre><span></span><span class="c1"># bad code!</span>
<span class="n">after_commit</span> <span class="ss">:thing</span><span class="p">,</span> <span class="ss">on</span><span class="p">:</span> <span class="ss">:update</span><span class="p">,</span> <span class="k">if</span><span class="p">:</span> <span class="ss">:is_active?</span>
<span class="n">after_commit</span> <span class="ss">:thing</span><span class="p">,</span> <span class="ss">on</span><span class="p">:</span> <span class="ss">:create</span>
</pre></div>
<p>One way to work around this is with this not so elegant but perfectly acceptable code, using <a href="https://stackoverflow.com/a/7183918/168143"><code>*_previously_changed?</code></a>:</p>
<div class="highlight"><pre><span></span><span class="n">after_commit</span> <span class="ss">:thing</span><span class="p">,</span> <span class="ss">on</span><span class="p">:</span> <span class="o">[</span><span class="ss">:update</span><span class="p">,</span> <span class="ss">:create</span><span class="o">]</span>

<span class="k">def</span> <span class="nf">thing</span>
  <span class="c1"># id_previously_changed? is only true when record is created</span>
  <span class="k">unless</span> <span class="n">id_previously_changed?</span>
    <span class="k">return</span> <span class="k">unless</span> <span class="n">is_active?</span>
  <span class="k">end</span>

<span class="c1"># ...</span>
<span class="k">end</span>
</pre></div>]]></content:encoded>
      </item>
  </channel>
</rss>