<?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom">
     <title>BigBinary Blog</title>
     <link href="https://www.bigbinary.com/feed.xml" rel="self"/>
     <link href="https://www.bigbinary.com/"/>
     <updated>2026-06-08T04:48:19+00:00</updated>
     <id>https://www.bigbinary.com/</id>
     <entry>
       <title><![CDATA[Ruby 2.5 added lazy proc allocation for block parameters]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-added-lazy-proc-allocation-for-block-parameters"/>
      <updated>2018-05-22T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-added-lazy-proc-allocation-for-block-parameters</id>
      <content type="html"><![CDATA[<pre><code class="language-ruby">irb&gt; def greetirb&gt;   yieldirb&gt; end  =&gt; :greetirb&gt;irb&gt; def greet_with_welcome(&amp;block)irb&gt;   puts 'Welcome'irb&gt;   greet(&amp;block)irb&gt; end  =&gt; :greet_with_welcomeirb&gt; greet_with_welcome { p 'BigBinary' }Welcome&quot;BigBinary&quot;  =&gt; &quot;BigBinary&quot;</code></pre><p>In Ruby 2.4 when we pass a block to a method, which further passes to anothermethod, Ruby creates a new <code>Proc</code> object by the given block before passing thisproc to the another method.</p><p>This creates unnecessary objects even when the block parameter is not accessed.It also creates a chain of <code>Proc</code> objects when the block parameter is passedthrough various methods.</p><p>Proc creation is one a heavyweight operation because we need to store all localvariables (represented by Env objects in MRI internal) in the heap.</p><p>Ruby 2.5 introduced a lazy proc allocation. Ruby 2.5 will not create a Procobject when passing a block to another method. Instead, it will pass the blockinformation. If the block is accessed somewhere else, then it creates a <code>Proc</code>object by the given block.</p><p>This results in lesser memory allocation and faster execution.</p><h4>Ruby 2.4</h4><pre><code class="language-ruby">irb&gt; require 'benchmark'  =&gt; trueirb&gt; def greetirb&gt;   yieldirb&gt; end  =&gt; :greetirb&gt;irb&gt; def greet_with_welcome(&amp;block)irb&gt;   puts 'Welcome'irb&gt;   greet(&amp;block)irb&gt; end  =&gt; :greet_with_welcomeirb&gt;irb&gt; Benchmark.measure { 1000.times { greet_with_welcome { 'BigBinary' } } }WelcomeWelcome.........  =&gt; #&lt;Benchmark::Tms:0x007fe6ab929de0 @label=&quot;&quot;, @real=0.022295999999187188, @cstime=0.0, @cutime=0.0, @stime=0.01, @utime=0.0, @total=0.01&gt;</code></pre><h4>Ruby 2.5</h4><pre><code class="language-ruby">irb&gt; require 'benchmark'  =&gt; trueirb&gt; def greetirb&gt;   yieldirb&gt; end  =&gt; :greetirb&gt;irb&gt; def greet_with_welcome(&amp;block)irb&gt;   puts 'Welcome'irb&gt;   greet(&amp;block)irb&gt; end  =&gt; :greet_with_welcomeirb&gt;  irb&gt; Benchmark.measure { 1000.times { greet_with_welcome { 'BigBinary' } } }WelcomeWelcome.........  =&gt; #&lt;Benchmark::Tms:0x00007fa4400871b8 @label=&quot;&quot;, @real=0.004612999997334555, @cstime=0.0, @cutime=0.0, @stime=0.001524000000000001, @utime=0.0030690000000000023, @total=0.004593000000000003&gt;</code></pre><p>As we can see, there is considerable improvement in execution time when a blockparam is passed in Ruby 2.5.</p><p>Here is the relevant <a href="https://github.com/ruby/ruby/commit/5ee9513a71">commit</a>and <a href="https://bugs.ruby-lang.org/issues/14045">discussion</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 adds Thread.report_on_exception by default]]></title>
       <author><name>Vishal Telangre</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-enables-thread-report_on_exception-by-default"/>
      <updated>2018-04-18T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-enables-thread-report_on_exception-by-default</id>
      <content type="html"><![CDATA[<p>Let's see what happens when an exception is raised inside a thread.</p><pre><code class="language-ruby">division_thread = Thread.new do  puts &quot;Calculating 4/0 in division_thread&quot;  puts &quot;Result is: #{4/0}&quot;  puts &quot;Exiting from division_thread&quot;endsleep 1puts &quot;In the main thread&quot;</code></pre><p>Execution of it looks like this.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby thread_example_1.rbCalculating 4/0 in division_threadIn the main thread</code></pre><p>Note that the last two lines from the block were not printed. Also notice thatafter failing in the thread the program continued to run in main thread. That'swhy we got the message &quot;In the main thread&quot;.</p><p>This is because the default behavior of Ruby is to silently ignore exceptions inthreads and then to continue to execute in the main thread.</p><h2>Enabling abort_on_exception to stop on failure</h2><p>If we want an exception in a thread to stop further processing both in thethread and in the main thread then we can enable <code>Thread[.#]abort_on_exception</code>on that thread to achieve that.</p><p>Notice that in the below code we are using <code>Thread.current</code>.</p><pre><code class="language-ruby">division_thread = Thread.new do  Thread.current.abort_on_exception = true  puts &quot;Calculating 4/0 in division_thread&quot;  puts &quot;Result is: #{4/0}&quot;  puts &quot;Exiting from division_thread&quot;endsleep 1puts &quot;In the main thread&quot;</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby thread_example_2.rbCalculating 4/0 in division_threadthread_example_2.rb:5:in `/': divided by 0 (ZeroDivisionError)  from thread_example_2.rb:5:in `block in &lt;main&gt;'</code></pre><p>As we can see once an exception was encountered in the thread then processingstopped on both in the thread and in the main thread.</p><p>Note that <code>Thread.current.abort_on_exception = true</code> activates this behavioronly for the current thread.</p><p>If we want this behavior globally for all the threads then we need to use<code>Thread.abort_on_exception = true</code>.</p><h2>Running program with debug flag to stop on failure</h2><p>Let's run the original code with <code>--debug</code> option.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby --debug thread_example_1.rbthread_example_1.rb:1: warning: assigned but unused variable - division_threadCalculating 4/0 in division_threadException `ZeroDivisionError' at thread_example_1.rb:3 - divided by 0Exception `ZeroDivisionError' at thread_example_1.rb:7 - divided by 0thread_example_1.rb:3:in `/': divided by 0 (ZeroDivisionError)  from thread_example_1.rb:3:in `block in &lt;main&gt;'</code></pre><p>In this case the exception is printed in detail and the code in main thread wasnot executed.</p><p>Usually when we execute a program with <code>--debug</code> option then the behavior of theprogram does not change. We expect the program to print more stuff but we do notexpect behavior to change. However in this case the <code>--debug</code> option changes thebehavior of the program.</p><h2>Running program with join on thread to stop on failure</h2><p>If a thread raises an exception and <code>abort_on_exception</code> and <code>$DEBUG</code> flags arenot set then that exception will be processed at the time of joining of thethread.</p><pre><code class="language-ruby">division_thread = Thread.new do  puts &quot;Calculating 4/0 in division_thread&quot;  puts &quot;Result is: #{4/0}&quot;  puts &quot;Exiting from division_thread&quot;enddivision_thread.joinputs &quot;In the main thread&quot;</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby thread_example_3.rbCalculating 4/0 in division_threadthread_example_3.rb:3:in `/': divided by 0 (ZeroDivisionError)  from thread_example_3.rb:3:in `block in &lt;main&gt;'</code></pre><p>Both <code>Thread#join</code> and <code>Thread#value</code> will stop processing in the thread and inthe main thread once an exception is encountered.</p><h2>Introduction of report_on_exception in Ruby 2.4</h2><p>Almost 6 years ago, <a href="https://github.com/headius">Charles Nutter (headius)</a> hadproposed that the exceptions raised in threads should be automatically loggedand reported, by default. To make his point, he explained issues similar to whatwe discussed above about the Ruby's behavior of silently ignoring exceptions inthreads. <a href="https://bugs.ruby-lang.org/issues/6647">Here</a> is the relevantdiscussion on his proposal.</p><p>Following are some of the notable points discussed.</p><ul><li>Enabling <code>Thread[.#]abort_on_exception</code>, by default, is not always a goodidea.</li><li>There should be a flag which, if enabled, would print the thread-killingexception info.</li><li>In many cases, people spawn one-off threads which are not hard-referencedusing <code>Thread#join</code> or <code>Thread#value</code>. Such threads gets garbage collected.Should it report the thread-killing exception at the time of garbagecollection if such a flag is enabled?</li><li>Should it warn using<a href="https://ruby-doc.org/core-2.4.0/Warning.html#method-i-warn"><code>Warning#warn</code></a>or redirect to STDERR device while reporting?</li></ul><p>Charles Nutter suggested that a configurable global flag<code>Thread.report_on_exception</code> and instance-level flag<code>Thread#report_on_exception</code> should be implemented having its default value as<code>true</code>. When set to <code>true</code>, it should report print exception information.</p><p>Matz and other core members approved that <code>Thread[.#]report_on_exception</code> can beimplemented having its default value set to <code>false</code>.</p><p>Charles Nutter, Benoit Daloze and other people demanded that it should be <code>true</code>by default so that programmers can be aware of the silently disappearing threadsbecause of exceptions.</p><p>Shyouhei Urabe <a href="https://bugs.ruby-lang.org/issues/6647#note-41">advised</a> thatdue to some technical challenges, the default value should be set to <code>false</code> soas this feature could land in Ruby. Once this feature is in then the defaultvalue can be changed in a later release.</p><p><a href="https://github.com/nobu">Nobuyoshi Nakada (nobu)</a> pushed an<a href="https://github.com/ruby/ruby/commit/2e71c752787e0c7659bd5e89b6c5d433eddfe13a">implementation</a>for <code>Thread[.#]report_on_exception</code> with a default value set to <code>false</code>. It wasreleased in Ruby 2.4.0.</p><p>Let's try enabling <code>report_on_exception</code> globally using<code>Thread.report_on_exception</code>.</p><pre><code class="language-ruby">Thread.report_on_exception = truedivision_thread = Thread.new do  puts &quot;Calculating 4/0 in division_thread&quot;  puts &quot;Result is: #{4/0}&quot;  puts &quot;Exiting from division_thread&quot;endaddition_thread = Thread.new do  puts &quot;Calculating nil+4 in addition_thread&quot;  puts &quot;Result is: #{nil+4}&quot;  puts &quot;Exiting from addition_thread&quot;endsleep 1puts &quot;In the main thread&quot;</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby thread_example_4.rbCalculating 4/0 in division_thread#&lt;Thread:0x007fb10f018200@thread_example_4.rb:3 run&gt; terminated with exception:thread_example_4.rb:5:in `/': divided by 0 (ZeroDivisionError)  from thread_example_4.rb:5:in `block in &lt;main&gt;'Calculating nil+4 in addition_thread#&lt;Thread:0x007fb10f01aca8@thread_example_4.rb:9 run&gt; terminated with exception:thread_example_4.rb:11:in `block in &lt;main&gt;': undefined method `+' for nil:NilClass (NoMethodError)In the main thread</code></pre><p>It now reports the exceptions in all threads. It prints that the<code>Thread:0x007fb10f018200</code> was<code>terminated with exception: divided by 0 (ZeroDivisionError)</code>. Similarly,another thread <code>Thread:0x007fb10f01aca8</code> was<code>terminated with exception: undefined method '+' for nil:NilClass (NoMethodError)</code>.</p><p>Instead of enabling it globally for all threads, we can enable it for aparticular thread using instance-level <code>Thread#report_on_exception</code>.</p><pre><code class="language-ruby">division_thread = Thread.new do  puts &quot;Calculating 4/0 in division_thread&quot;  puts &quot;Result is: #{4/0}&quot;  puts &quot;Exiting from division_thread&quot;endaddition_thread = Thread.new do  Thread.current.report_on_exception = true  puts &quot;Calculating nil+4 in addition_thread&quot;  puts &quot;Result is: #{nil+4}&quot;  puts &quot;Exiting from addition_thread&quot;endsleep 1puts &quot;In the main thread&quot;</code></pre><p>In the above case we have enabled <code>report_on_exception</code> flag just for<code>addition_thread</code>.</p><p>Let's execute it.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby thread_example_5.rbCalculating 4/0 in division_threadCalculating nil+4 in addition_thread#&lt;Thread:0x007f8e6b007f70@thread_example_5.rb:7 run&gt; terminated with exception:thread_example_5.rb:11:in `block in &lt;main&gt;': undefined method `+' for nil:NilClass (NoMethodError)In the main thread</code></pre><p>Notice how it didn't report the exception which killed thread <code>division_thread</code>.As expected, it reported the exception that killed thread <code>addition_thread</code>.</p><p>With the above changes ruby reports the exception as soon as it encounters.However if these threads are joined then they will still raise exception.</p><pre><code class="language-ruby">division_thread = Thread.new do  Thread.current.report_on_exception = true  puts &quot;Calculating 4/0 in division_thread&quot;  puts &quot;Result is: #{4/0}&quot;  puts &quot;Exiting from division_thread&quot;endbegin  division_thread.joinrescue =&gt; exception  puts &quot;Explicitly caught - #{exception.class}: #{exception.message}&quot;endputs &quot;In the main thread&quot;</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby thread_example_6.rbCalculating 4/0 in division_thread#&lt;Thread:0x007f969d00d828@thread_example_6.rb:1 run&gt; terminated with exception:thread_example_6.rb:5:in `/': divided by 0 (ZeroDivisionError)  from thread_example_6.rb:5:in `block in &lt;main&gt;'Explicitly caught - ZeroDivisionError: divided by 0In the main thread</code></pre><p>See how we were still be able to handle the exception raised in<code>division_thread</code> above after joining it despite it reported it before due to<code>Thread#report_on_exception</code> flag.</p><h2>report_on_exception defaults to true in Ruby 2.5</h2><p><a href="https://github.com/eregon">Benoit Daloze (eregon)</a> strongly advocated that boththe <code>Thread.report_on_exception</code> and <code>Thread#report_on_exception</code> should havedefault value as <code>true</code>. <a href="https://bugs.ruby-lang.org/issues/14143">Here</a> is therelevant feature request.</p><p>After <a href="https://bugs.ruby-lang.org/issues/14143#note-9">approval from Matz</a>,Benoit Daloze pushed the<a href="https://github.com/ruby/ruby/search?utf8=%E2%9C%93&amp;q=Feature+%5C%2314143&amp;type=Commits">implementation</a>by fixing the failing tests and silencing the unnecessary verbose warnings.</p><p>It was released as part of Ruby 2.5.</p><p>Now in ruby 2.5 we can simply write like this.</p><pre><code class="language-ruby">division_thread = Thread.new do  puts &quot;Calculating 4/0 in division_thread&quot;  puts &quot;Result is: #{4/0}&quot;  puts &quot;Exiting from division_thread&quot;endaddition_thread = Thread.new do  puts &quot;Calculating nil+4 in addition_thread&quot;  puts &quot;Result is: #{nil+4}&quot;  puts &quot;Exiting from addition_thread&quot;endsleep 1puts &quot;In the main thread&quot;</code></pre><p>Let's execute it with Ruby 2.5.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby thread_example_7.rbCalculating 4/0 in division_thread#&lt;Thread:0x00007f827689a238@thread_example_7.rb:1 run&gt; terminated with exception (report_on_exception is true):Traceback (most recent call last):  1: from thread_example_7.rb:3:in `block in &lt;main&gt;'thread_example_7.rb:3:in `/': divided by 0 (ZeroDivisionError)Calculating nil+4 in addition_thread#&lt;Thread:0x00007f8276899b58@thread_example_7.rb:7 run&gt; terminated with exception (report_on_exception is true):Traceback (most recent call last):thread_example_7.rb:9:in `block in &lt;main&gt;': undefined method `+' for nil:NilClass (NoMethodError)In the main thread</code></pre><p>We can disable the thread exception reporting globally using<code>Thread.report_on_exception = false</code> or for a particular thread using<code>Thread.current.report_on_exception = false</code>.</p><h2>Future Possibilities</h2><p>In addition to this feature, Charles Nutter also<a href="https://bugs.ruby-lang.org/issues/14143#note-4">suggested</a> that it will be goodif there exists a callback handler which can accept a block to be executed whena thread dies due to an exception. The callback handler can be at global levelor it can be for a specific thread.</p><pre><code class="language-ruby">Thread.on_exception do  # some stuffend</code></pre><p>In the absence of such handler libraries need to resort to custom code to handleexceptions.<a href="https://github.com/mperham/sidekiq/blob/a60a91d3dd857592a532965f0701d285f13f28f1/lib/sidekiq/util.rb#L15-L27">Here is how</a>Sidekiq handles exceptions raised in threads.</p><p>Important thing to note is that <code>report_on_exception</code> does not change behaviorof the code. It does more reporting when a thread dies and when it comes tothread dies more reporting is a good thing.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 supports measuring branch and method coverages]]></title>
       <author><name>Vishal Telangre</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-supports-measuring-branch-and-method-coverages"/>
      <updated>2018-04-11T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-supports-measuring-branch-and-method-coverages</id>
      <content type="html"><![CDATA[<p>Ruby comes with<a href="https://ruby-doc.org/stdlib-2.5.0/libdoc/coverage/rdoc/Coverage.html">Coverage</a>,a simple standard library for test coverage measurement for a long time.</p><h2>Before Ruby 2.5</h2><p>Before Ruby 2.5, we could measure just the line coverage using <code>Coverage</code>.</p><p>Line coverage tells us whether a line is executed or not. If executed, then howmany times that line was executed.</p><p>We have a file called <code>score.rb</code>.</p><pre><code class="language-ruby">score = 33if score &gt;= 40  p :PASSEDelse  p :FAILEDend</code></pre><p>Now create another file <code>score_coverage.rb</code>.</p><pre><code class="language-ruby">require &quot;coverage&quot;Coverage.startload &quot;score.rb&quot;p Coverage.result</code></pre><p>We used <code>Coverage#start</code> method to measure the coverage of <code>score.rb</code> file.<code>Coverage#result</code> returns the coverage result.</p><p>Let's run it with Ruby 2.4.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby score_coverage.rb:FAILED{ &quot;score.rb&quot;=&gt; [1, nil, 1, 0, nil, 1, nil] }</code></pre><p>Let's look at the output. Each value in the array <code>[1, nil, 1, 0, nil, 1, nil]</code>denotes the count of line executions by the interpreter for each line in<code>score.rb</code> file.</p><p>This array is also called the &quot;line coverage&quot; of <code>score.rb</code> file.</p><p>A <code>nil</code> value in line coverage array means coverage is disabled for thatparticular line number or it is not a relevant line. Lines like <code>else</code>, <code>end</code>and blank lines have line coverage disabled.</p><p>Here's how we can read above line coverage result.</p><ul><li>Line number 1 (i.e. 0th index in the above result array) was executed once.</li><li>Coverage was disabled for line number 2 (i.e. index 1) as it is blank.</li><li>Line number 3 (i.e. index 2) was executed once.</li><li>Line number 4 did not execute.</li><li>Coverage was disabled for line number 5 as it contains only <code>else</code> clause.</li><li>Line number 6 was executed once.</li><li>Coverage was disabled for line number 7 as it contains just <code>end</code> keyword.</li></ul><h2>After Ruby 2.5</h2><p>There was a <a href="https://github.com/ruby/ruby/pull/511">pull request</a> opened in 2014to add method coverage and decision coverage metrics in Ruby. It was<a href="https://github.com/ruby/ruby/pull/511#issuecomment-328753499">rejected</a> by<a href="https://github.com/mame">Yusuke Endoh</a> as he saw some issues with it andmentioned that he was also working on a similar implementation.</p><p>In Ruby 2.5, Yusuke Endoh<a href="https://bugs.ruby-lang.org/issues/13901">added branch coverage and method coverage feature</a>to the <code>Coverage</code> library.</p><p>Let's see what's changed in <code>Coverage</code> library in Ruby 2.5.</p><h3>Line Coverage</h3><p>If we execute above example using Ruby 2.5, we will see no change in the result.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby score_coverage.rb:FAILED{ &quot;score.rb&quot; =&gt; [1, nil, 1, 0, nil, 1, nil] }</code></pre><p>This behavior is maintained to ensure that the <code>Coverage#start</code> API stays 100%backward compatible.</p><p>If we explicitly enable <code>lines</code> option on <code>Coverage#start</code> method in the above<code>score_coverage.rb</code> file, the coverage result will be different now.</p><pre><code class="language-ruby">require &quot;coverage&quot;Coverage.start(lines: true)load &quot;score.rb&quot;p Coverage.result</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby score_coverage.rb:FAILED{ &quot;score.rb&quot; =&gt; {    :lines =&gt; [1, nil, 1, 0, nil, 1, nil]  }}</code></pre><p>We can see that the coverage result is now a hash which reads that the<code>score.rb</code> file has <code>lines</code> coverage as <code>[1, nil, 1, 0, nil, 1, nil]</code>.</p><h3>Branch Coverage</h3><p>Branch coverage helps us identify which branches are executed and which ones arenot executed.</p><p>Let's see how to get branch coverage.</p><p>We will update the <code>score_coverage.rb</code> by enabling <code>branches</code> option.</p><pre><code class="language-ruby">require &quot;coverage&quot;Coverage.start(branches: true)load &quot;score.rb&quot;p Coverage.result</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby score_coverage.rb:FAILED{ &quot;score.rb&quot; =&gt;  { :branches =&gt; {      [:if, 0, 3, 0, 7, 3] =&gt; {        [:then, 1, 4, 2, 4, 15] =&gt; 0,        [:else, 2, 6, 2, 6, 15] =&gt; 1      }    }  }}</code></pre><p>Here is how to read the data in array.</p><pre><code class="language-ruby">[  BRANCH_TYPE,  UNIQUE_ID,  START_LINE_NUMBER,  START_COLUMN_NUMBER,  END_LINE_NUMBER,  END_COLUMN_NUMBER]</code></pre><p>Please note that column numbers start from 0 and line numbers start from 1.</p><p>Let's try to read above printed branch coverage result.</p><p><code>[:if, 0, 3, 0, 7, 3]</code> reads that <code>if</code> statement starts at line 3 &amp; column 0 andends at line 7 &amp; column 3.</p><p><code>[:then, 1, 4, 2, 4, 15]</code> reads that <code>then</code> clause starts at line 4 &amp; column 2and ends at line 4 &amp; column 15.</p><p>Similarly, <code>[:else, 2, 6, 2, 6, 15]</code> reads that <code>else</code> clause starts at line 6 &amp;column 2 and ends at line 6 &amp; column 15.</p><p>Most importantly as per the branch coverage format, we can see that the branchfrom <code>if</code> to <code>then</code> was never executed since <code>COUNTER</code> is <code>0</code>. The anotherbranch from <code>if</code> to <code>else</code> was executed once since <code>COUNTER</code> is <code>1</code>.</p><h3>Method Coverage</h3><p>Measuring method coverage helps us identify which methods were invoked and whichwere not.</p><p>We have a file <code>grade_calculator.rb</code>.</p><pre><code class="language-ruby">students_scores = { &quot;Sam&quot; =&gt; [53, 91, 72],                    &quot;Anna&quot; =&gt; [91, 97, 95],                    &quot;Bob&quot; =&gt; [33, 69, 63] }def average(scores)  scores.reduce(&amp;:+)/scores.sizeenddef grade(average_score)  case average_score  when 90.0..100.0 then :A  when 80.0..90.0 then :B  when 70.0..80.0 then :C  when 60.0..70.0 then :D  else :F  endenddef greet  puts &quot;Congratulations!&quot;enddef warn  puts &quot;Try hard next time!&quot;endstudents_scores.each do |student_name, scores|  achieved_grade = grade(average(scores))  puts &quot;#{student_name}, you've got '#{achieved_grade}' grade.&quot;  if achieved_grade == :A    greet  elsif achieved_grade == :F    warn  end  putsend</code></pre><p>To measure method coverage of above file, let's create<code>grade_calculator_coverage.rb</code> by enabling <code>methods</code> option on <code>Coverage#start</code>method.</p><pre><code class="language-ruby">require &quot;coverage&quot;Coverage.start(methods: true)load &quot;grade_calculator.rb&quot;p Coverage.result</code></pre><p>Let's run it using Ruby 2.5.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby grade_calculator_coverage.rbSam, you've got 'C' grade.Anna, you've got 'A' grade.Congratulations!Bob, you've got 'F' grade.Try hard next time!{ &quot;grade_calculator.rb&quot; =&gt; {    :methods =&gt; {      [Object, :warn, 23, 0, 25, 3] =&gt; 1,      [Object, :greet, 19, 0, 21, 3] =&gt; 1,      [Object, :grade, 9, 0, 17, 3] =&gt; 3,      [Object, :average, 5, 0, 7, 3] =&gt; 3    }  }}</code></pre><p>The format of method coverage result is defined as shown below.</p><pre><code class="language-ruby">[ CLASS_NAME,  METHOD_NAME,  START_LINE_NUMBER,  START_COLUMN_NUMBER,  END_LINE_NUMBER,  END_COLUMN_NUMBER ]</code></pre><p>Therefore, <code>[Object, :grade, 9, 0, 17, 3] =&gt; 3</code> reads that the <code>Object#grade</code>method which starts from line 9 &amp; column 0 to line 17 &amp; column 3 was invoked 3times.</p><h2>Conclusion</h2><p>We can measure all coverages at once also.</p><pre><code class="language-ruby">Coverage.start(lines: true, branches: true, methods: true)</code></pre><p>What's the use of these different types of coverages anyway?</p><p>Well, one use case is to integrate this in a test suite and to determine whichlines, branches and methods are executed and which ones are not executed by thetest. Further, we can sum up these and evaluate total coverage of a test suite.</p><p>Author of this feature, Yusuke Endoh has released<a href="https://github.com/mame/coverage-helpers">coverage-helpers</a> gem which allowsfurther advanced manipulation and processing of coverage results obtained using<code>Coverage#result</code>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 adds Exception#full_message method]]></title>
       <author><name>Vishal Telangre</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-adds-exception-full_message-method"/>
      <updated>2018-03-13T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-adds-exception-full_message-method</id>
      <content type="html"><![CDATA[<p>Before Ruby 2.5, if we want to log a caught exception, we would need to formatit ourselves.</p><pre><code class="language-ruby">class AverageService  attr_reader :numbers, :coerced_numbers  def initialize(numbers)    @numbers = numbers    @coerced_numbers = coerce_numbers  end  def average    sum / count  end  private  def coerce_numbers    numbers.map do |number|      begin        Float(number)      rescue Exception =&gt; exception        puts &quot;#{exception.message} (#{exception.class})\n\t#{exception.backtrace.join(&quot;\n\t&quot;)}&quot;        puts &quot;Coercing '#{number}' as 0.0\n\n&quot;        0.0      end    end  end  def sum    coerced_numbers.map(&amp;:to_f).sum  end  def count    coerced_numbers.size.to_f  endendaverage = AverageService.new(ARGV).averageputs &quot;Average is: #{average}&quot;</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby average_service.rb 5 4f 7 1s0invalid value for Float(): &quot;4f&quot; (ArgumentError)average_service.rb:18:in `Float'average_service.rb:18:in `block in coerce_numbers'average_service.rb:16:in `map'average_service.rb:16:in `coerce_numbers'average_service.rb:6:in `initialize'average_service.rb:37:in `new'average_service.rb:37:in `&lt;main&gt;'Coercing '4f' as 0.0invalid value for Float(): &quot;1s0&quot; (ArgumentError)average_service.rb:18:in `Float'average_service.rb:18:in `block in coerce_numbers'average_service.rb:16:in `map'average_service.rb:16:in `coerce_numbers'average_service.rb:6:in `initialize'average_service.rb:37:in `new'average_service.rb:37:in `&lt;main&gt;'Coercing '1s0' as 0.0Average of [5.0, 0.0, 7.0, 0.0] is: 3.0</code></pre><p>It was <a href="https://bugs.ruby-lang.org/issues/14141">proposed</a> that there should bea simple method to print the caught exception using the same format that rubyuses while printing an uncaught exception.</p><p>Some of the proposed method names were <code>display</code>, <code>formatted</code>, <code>to_formatted_s</code>,<code>long_message</code>, and <code>full_message</code>.</p><p>Matz <a href="https://bugs.ruby-lang.org/issues/14141#note-15">approved</a> the<code>Exception#full_message</code> method name.</p><p>In Ruby 2.5, we can re-write above example as follows.</p><pre><code class="language-ruby">class AverageService  attr_reader :numbers, :coerced_numbers  def initialize(numbers)    @numbers = numbers    @coerced_numbers = coerce_numbers  end  def average    sum / count  end  private  def coerce_numbers    numbers.map do |number|      begin        Float(number)      rescue Exception =&gt; exception        puts exception.full_message        puts &quot;Coercing '#{number}' as 0.0\n\n&quot;        0.0      end    end  end  def sum    coerced_numbers.map(&amp;:to_f).sum  end  def count    coerced_numbers.size.to_f  endendaverage = AverageService.new(ARGV).averageputs &quot;Average is: #{average}&quot;</code></pre><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby average_service.rb 5 4f 7 1s0Traceback (most recent call last):6: from average_service.rb:37:in `&lt;main&gt;'5: from average_service.rb:37:in `new'4: from average_service.rb:6:in `initialize'3: from average_service.rb:16:in `coerce_numbers'2: from average_service.rb:16:in `map'1: from average_service.rb:18:in `block in coerce_numbers'average_service.rb:18:in `Float': invalid value for Float(): &quot;4f&quot; (ArgumentError)Coercing '4f' as 0.0Traceback (most recent call last):6: from average_service.rb:37:in `&lt;main&gt;'5: from average_service.rb:37:in `new'4: from average_service.rb:6:in `initialize'3: from average_service.rb:16:in `coerce_numbers'2: from average_service.rb:16:in `map'1: from average_service.rb:18:in `block in coerce_numbers'average_service.rb:18:in `Float': invalid value for Float(): &quot;1s0&quot; (ArgumentError)Coercing '1s0' as 0.0Average of [5.0, 0.0, 7.0, 0.0] is: 3.0</code></pre><p>Note that, Ruby 2.5 prints exception backtrace in reverse order if STDERR isunchanged and is a TTY as discussed<a href="https://blog.bigbinary.com/2018/03/07/ruby-2-5-prints-backstrace-and-error-message-in-reverse-order.html">in our previous blog post</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 prints backtrace & error message in reverse]]></title>
       <author><name>Vishal Telangre</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-prints-backstrace-and-error-message-in-reverse-order"/>
      <updated>2018-03-07T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-prints-backstrace-and-error-message-in-reverse-order</id>
      <content type="html"><![CDATA[<p>Stack trace or backtrace is a sequential representation of the stack of methodcalls in a program which gets printed when an exception is raised. It is oftenused to find out the exact location in a program from where the exception wasraised.</p><h2>Before Ruby 2.5</h2><p>Before Ruby 2.5, the printed backtrace contained the exception class and theerror message at the top. Next line contained where in the program the exceptionwas raised. Next we got more lines which contained cascaded method calls.</p><p>Consider a simple Ruby program.</p><pre><code class="language-ruby">class DivisionService  attr_reader :a, :b  def initialize(a, b)    @a, @b = a.to_i, b.to_i  end  def divide    puts a / b  endendDivisionService.new(ARGV[0], ARGV[1]).divide</code></pre><p>Let's execute it using Ruby 2.4.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.4.0 ruby division_service.rb 5 0division_service.rb:9:in `/': divided by 0 (ZeroDivisionError)from division_service.rb:9:in `divide'from division_service.rb:13:in `&lt;main&gt;'</code></pre><p>In the printed backtrace above, the first line shows the location, error messageand the exception class name; whereas the subsequent lines shows the callermethod names and their locations. Each line in the backtrace above is oftenconsidered as a stack frame placed on the call stack.</p><p>Most of the times, a backtrace has so many lines that it makes it very difficultto fit the whole backtrace in the visible viewport of the terminal.</p><p>Since the backtrace is printed in top to bottom order the meaningful informationlike error message, exception class and the exact location where the exceptionwas raised is displayed at top of the backtrace. It means developers often needto scroll to the top in the terminal window to find out what went wrong.</p><h2>After Ruby 2.5</h2><p>Over 4 years ago an <a href="https://bugs.ruby-lang.org/issues/8661">issue</a> was createdto make printing of backtrace in reverse order configurable.</p><p>After much discussion Nobuyoshi Nakada made the commit to print backtrace anderror message<a href="https://github.com/ruby/ruby/commit/5318154fe1ac6f8dff014988488b9e063988a105">in reverse order</a>only when the error output device (<code>STDERR</code>) is a TTY (i.e. a terminal). Messagewill not be printed in reverse order if the original <code>STDERR</code> is attached tosomething like a <code>File</code> object.</p><p><a href="https://github.com/ruby/ruby/blob/5318154fe1ac6f8dff014988488b9e063988a105/eval_error.c#L187-L195">Look at the code here</a>where the check happens if <code>STDERR</code> is a TTY and is unchanged.</p><p>Let's execute the same program using Ruby 2.5.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby division_service.rb 5 0Traceback (most recent call last):2: from division_service.rb:13:in `&lt;main&gt;'1: from division_service.rb:9:in `divide'division_service.rb:9:in `/': divided by 0 (ZeroDivisionError)$</code></pre><p>We can notice two new changes in the above backtrace.</p><ol><li>The error message and exception class is printed last (i.e. at the bottom).</li><li>The stack also<a href="https://github.com/ruby/ruby/commit/87023a1dcc548f0eb7ccfacd64d795093d1c7e17">adds frame number</a>when printing in reverse order.</li></ol><p>This feature makes the debugging convenient when the backtrace size is a quitebig and cannot fit in the terminal window. We can easily see the error messagewithout scrolling up now.</p><p>Note that, the <code>Exception#backtrace</code> attribute still holds an array of stackframes like before in the top to bottom order.</p><p>So if we rescue the caught exception and print the backtrace manually</p><pre><code class="language-ruby">class DivisionService  attr_reader :a, :b  def initialize(a, b)    @a, @b = a.to_i, b.to_i  end  def divide    puts a / b  endendbegin  DivisionService.new(ARGV[0], ARGV[1]).dividerescue Exception =&gt; e  puts &quot;#{e.class}: #{e.message}&quot;  puts e.backtrace.join(&quot;\n&quot;)end</code></pre><p>we will get the old behavior.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby division_service.rb 5 0ZeroDivisionError: divided by 0division_service.rb:9:in `/'division_service.rb:9:in `divide'division_service.rb:16:in `&lt;main&gt;'$</code></pre><p>Also, note that if we assign <code>STDERR</code> with a <code>File</code> object, thus making it anon-TTY</p><pre><code class="language-ruby">puts &quot;STDERR is a TTY? [before]: #{$stderr.tty?}&quot;$stderr = File.new(&quot;stderr.log&quot;, &quot;w&quot;)$stderr.sync = trueputs &quot;STDERR is a TTY? [after]: #{$stderr.tty?}&quot;class DivisionService  attr_reader :a, :b  def initialize(a, b)    @a, @b = a.to_i, b.to_i  end  def divide    puts a / b  endendDivisionService.new(ARGV[0], ARGV[1]).divide</code></pre><p>we can get the old behavior but the backtrace would be written to the specifiedfile and not to <code>STDERR</code>.</p><pre><code class="language-ruby">$ RBENV_VERSION=2.5.0 ruby division_service.rb 5 0STDERR is a TTY? [before]: trueSTDERR is a TTY? [after]: false$ cat stderr.logdivision_service.rb:14:in `/': divided by 0 (ZeroDivisionError)from division_service.rb:14:in `divide'from division_service.rb:18:in `&lt;main&gt;'$</code></pre><p>This feature has been tagged as<a href="https://github.com/ruby/ruby/commit/5b58d8e6d8d187f37750540535f741cf6c2b661a">experimental feature</a>.What it means is that Ruby team is<a href="https://bugs.ruby-lang.org/issues/8661#journal-64903-notes">gathering feedback</a>on this feature.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 added Hash#slice method]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-added-hash-slice-method"/>
      <updated>2018-02-06T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-added-hash-slice-method</id>
      <content type="html"><![CDATA[<h4>Ruby 2.4</h4><p>Let's say we have a hash<code>{ id: 1, name: 'Ruby 2.5', description: 'BigBinary Blog' }</code> and we want toselect key value pairs having the keys <code>name</code> and <code>description</code>.</p><p>We can use the<a href="https://ruby-doc.org/core-2.4.2/Hash.html#method-i-select">Hash#select</a> method.</p><pre><code class="language-ruby">irb&gt; blog = { id: 1, name: 'Ruby 2.5', description: 'BigBinary Blog' }  =&gt; {:id=&gt;1, :name=&gt;&quot;Ruby 2.5&quot;, :description=&gt;&quot;BigBinary Blog&quot;}irb&gt; blog.select { |key, value| [:name, :description].include?(key) }  =&gt; {:name=&gt;&quot;Ruby 2.5&quot;, :description=&gt;&quot;BigBinary Blog&quot;}</code></pre><p><a href="https://bugs.ruby-lang.org/users/5184">Matzbara Masanao</a> proposed a simplemethod to take care of this problem.</p><p>Some of the names proposed were <code>choice</code> and <code>pick</code>.</p><p><a href="https://twitter.com/yukihiro_matz">Matz</a> suggested the name <code>slice</code> since thismethod is ActiveSupport compatible.</p><h4>Ruby 2.5.0</h4><pre><code class="language-ruby">irb&gt; blog = { id: 1, name: 'Ruby 2.5', description: 'BigBinary Blog' }  =&gt; {:id=&gt;1, :name=&gt;&quot;Ruby 2.5&quot;, :description=&gt;&quot;BigBinary Blog&quot;}irb&gt; blog.slice(:name, :description)  =&gt; {:name=&gt;&quot;Ruby 2.5&quot;, :description=&gt;&quot;BigBinary Blog&quot;}</code></pre><p>So, now we can use a simple method <code>slice</code> to select key value pairs from a hashwith specified keys.</p><p>Here is the relevant <a href="https://github.com/ruby/ruby/commit/6c50bdda0b">commit</a>and <a href="https://bugs.ruby-lang.org/issues/13563">discussion</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 allows creating structs with keyword arguments]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-allows-creating-structs-with-keyword-arguments"/>
      <updated>2018-01-16T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-allows-creating-structs-with-keyword-arguments</id>
      <content type="html"><![CDATA[<p>In Ruby, structs can be created using positional arguments.</p><pre><code class="language-ruby">Customer = Struct.new(:name, :email)Customer.new(&quot;John&quot;, &quot;john@example.com&quot;)</code></pre><p>This approach works when the arguments list is short. When arguments listincreases then it gets harder to track which position maps to which value.</p><p>Here if we pass keyword argument then we won't get any error. But the values arenot what we wanted.</p><pre><code class="language-ruby">Customer.new(name: &quot;John&quot;, email: &quot;john@example.com&quot;)=&gt; #&lt;struct Customer name={:name=&gt;&quot;John&quot;, :email=&gt;&quot;john@example.com&quot;}, email=nil&gt;</code></pre><p>Ruby 2.5 introduced<a href="https://bugs.ruby-lang.org/issues/11925">creating structs using keyword arguments</a>.Relevant pull request is <a href="https://github.com/ruby/ruby/pull/1771/files">here</a>.</p><p>However this introduces a problem. How do we indicate to <code>Struct</code> if we want topass arguments using position or keywords.</p><p>Takashi Kokubun<a href="https://bugs.ruby-lang.org/issues/11925#journal-68208-private_notes">suggested</a>to use <code>keyword_argument</code> as an identifier.</p><pre><code class="language-ruby">Customer = Struct.new(:name, :email, keyword_argument: true)Customer.create(name: &quot;John&quot;, email: &quot;john@example.com&quot;)</code></pre><p>Matz<a href="https://bugs.ruby-lang.org/issues/11925#journal-68295-private_notes">suggested</a>to change the name to <code>keyword_init</code>.</p><p>So in Ruby 2.5 we can create structs using keywords as long as we are passing<code>keyword_init</code>.</p><pre><code class="language-ruby">Customer = Struct.new(:name, :email, keyword_init: true)Customer.new(name: &quot;John&quot;, email: &quot;john@example.com&quot;)=&gt; #&lt;struct Customer name=&quot;John&quot;, email=&quot;john@example.com&quot;&gt;</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 adds Hash#transform_keys method]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-adds-hash-transform_keys-method"/>
      <updated>2018-01-09T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-adds-hash-transform_keys-method</id>
      <content type="html"><![CDATA[<p>Ruby 2.4 added<a href="https://bigbinary.com/blog/ruby-2-4-added-hash-transform-values-and-its-destructive-version-from-active-support">Hash#transform_values</a>method to transform values of the hash.</p><p>In Ruby 2.5, a similar method<a href="https://bugs.ruby-lang.org/issues/13583">Hash#transform_keys</a> is added fortransforming keys of the hash.</p><pre><code class="language-ruby">&gt;&gt; h = { name: &quot;John&quot;, email: &quot;john@example.com&quot; }=&gt; {:name=&gt;&quot;John&quot;, :email=&gt;&quot;john@example.com&quot;}&gt;&gt; h.transform_keys { |k| k.to_s }=&gt; {&quot;name&quot;=&gt;&quot;John&quot;, &quot;email&quot;=&gt;&quot;john@example.com&quot;}</code></pre><p>The bang sibling of this method, <code>Hash#transform_keys!</code> is also added whichchanges the hash in place.</p><p>These two methods are already present in<a href="http://guides.rubyonrails.org/active_support_core_extensions.html#transform-keys-and-transform-keys-bang">Active Support from Rails</a>and are natively supported in Ruby now.</p><p>Rails master is already supporting<a href="https://github.com/rails/rails/commit/f213e926892">using the native methods</a> ifsupported by the Ruby version.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 enumerable predicates accept pattern argument]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-enumerable-predicates-accept-pattern-argument"/>
      <updated>2018-01-02T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-enumerable-predicates-accept-pattern-argument</id>
      <content type="html"><![CDATA[<p>Ruby 2.5.0 was recently<a href="https://www.ruby-lang.org/en/news/2017/12/25/ruby-2-5-0-released/">released</a>.</p><p>Ruby has sequence predicates such as <code>all?</code>, <code>none?</code>, <code>one?</code> and <code>any?</code> whichtake a block and evaluate that by passing every element of the sequence to it.</p><pre><code class="language-ruby">if queries.any? { |sql| /LEFT OUTER JOIN/i =~ sql }logger.log &quot;Left outer join detected&quot;end</code></pre><p>Ruby 2.5 allows using a shorthand for this by<a href="https://bugs.ruby-lang.org/issues/11286">passing a pattern argument</a>.Internally <code>case equality operator(===)</code> is used against every element of thesequence and the pattern argument.</p><pre><code class="language-ruby">if queries.any?(/LEFT OUTER JOIN/i)logger.log &quot;Left outer join detected&quot;end# Translates to:queries.any? { |sql| /LEFT OUTER JOIN/i === sql }</code></pre><p>This allows us to write concise and shorthand expressions where block is onlyused for comparisons. This feature is applicable to <code>all?</code>, <code>none?</code>, <code>one?</code> and<code>any?</code> methods.</p><h3>Similarities with Enumerable#grep</h3><p>This feature is based on how <code>Enumerable#grep</code> works. <code>grep</code> returns an array ofevery element in the sequence for which the <code>case equality operator(===)</code>returns true by applying the pattern. In this case, the <code>all?</code> and friendsreturn true or false.</p><p>There is a <a href="https://bugs.ruby-lang.org/issues/14197">proposal</a> to add it for<code>select</code> and <code>reject</code> as well.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 requires pp by default]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-requires-pp-by-default"/>
      <updated>2017-12-20T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-requires-pp-by-default</id>
      <content type="html"><![CDATA[<p>Ruby 2.5.0-preview1 was recently<a href="https://www.ruby-lang.org/en/news/2017/10/10/ruby-2-5-0-preview1-released/">released</a>.</p><p>Ruby allows pretty printing of objects using<a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/pp/rdoc/PP.html">pp method</a>.</p><p>Before Ruby 2.5, we had to require PP explicitly before using it. Even theofficial documentation states that &quot;All examples assume you have loaded the PPclass with require 'pp'&quot;.</p><pre><code class="language-ruby">&gt;&gt; months = %w(January February March)=&gt; [&quot;January&quot;, &quot;February&quot;, &quot;March&quot;]&gt;&gt; pp monthsNoMethodError: undefined method `pp' for main:ObjectDid you mean?  pfrom (irb):5from /Users/prathamesh/.rbenv/versions/2.4.1/bin/irb:11:&gt;&gt; require 'pp'=&gt; true&gt;&gt; pp months[&quot;January&quot;, &quot;February&quot;, &quot;March&quot;]=&gt; [&quot;January&quot;, &quot;February&quot;, &quot;March&quot;]</code></pre><p>In Ruby 2.5, we don't need to require pp. It<a href="https://bugs.ruby-lang.org/issues/14123">gets required by default</a>. We can useit directly.</p><pre><code class="language-ruby">&gt;&gt; months = %w(January February March)=&gt; [&quot;January&quot;, &quot;February&quot;, &quot;March&quot;]&gt;&gt; pp months[&quot;January&quot;, &quot;February&quot;, &quot;March&quot;]=&gt; [&quot;January&quot;, &quot;February&quot;, &quot;March&quot;]</code></pre><p>This feature was added after Ruby 2.5.0 preview 1 was released, so it's notpresent in the preview. It's present in<a href="https://github.com/ruby/ruby">Ruby trunk</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Array#prepend and Array#append in Ruby 2.5]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/array-prepend-and-array-append-in-ruby-2-5"/>
      <updated>2017-12-19T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/array-prepend-and-array-append-in-ruby-2-5</id>
      <content type="html"><![CDATA[<p>Ruby has <code>Array#unshift</code> to prepend an element to the start of an array and<code>Array#push</code> to append an element to the end of an array.</p><p>The names of these methods are not very intuitive. Active Support from Railsalready has aliases for<a href="https://github.com/rails/rails/blob/e48704db8e6021b690b1fe2b362c7cb2e624e173/activesupport/lib/active_support/core_ext/array/prepend_and_append.rb">the unshift and push methods</a>, namely <code>prepend</code> and <code>append</code>.</p><p>In Ruby 2.5, these methods<a href="https://bugs.ruby-lang.org/issues/12746">are added in the Ruby language itself</a>.</p><pre><code class="language-ruby">&gt;&gt; a = [&quot;hello&quot;]=&gt; [&quot;hello&quot;]&gt;&gt; a.append &quot;world&quot;=&gt; [&quot;hello&quot;, &quot;world&quot;]&gt;&gt; a.prepend &quot;Hey&quot;=&gt; [&quot;Hey&quot;, &quot;hello&quot;, &quot;world&quot;]&gt;&gt;</code></pre><p>They are implemented as aliases to the original <code>unshift</code> and <code>push</code> methods sothere is no change in the behavior.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 added yield_self]]></title>
       <author><name>Vijay Kumar Agrawal</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-added-yield_self"/>
      <updated>2017-12-12T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-added-yield_self</id>
      <content type="html"><![CDATA[<p>Ruby 2.5 added a new method named<a href="https://bugs.ruby-lang.org/issues/6721">yield_self</a>. It yields the receiver tothe given block and returns output of the last statement in the block.</p><pre><code class="language-ruby">irb&gt; &quot;Hello&quot;.yield_self { |str| str + &quot; World&quot; }  =&gt; &quot;Hello World&quot;</code></pre><h4>How is it different from <code>try</code> in Rails ?</h4><p>Without a method argument <a href="https://apidock.com/rails/v4.2.7/Object/try">try</a>behaves similar to <code>yield_self</code>. It would yield to the given block unless thereceiver is nil and returns the output of the last statement in the block.</p><pre><code class="language-ruby">irb&gt; &quot;Hello&quot;.try { |str| str + &quot; World&quot; }  =&gt; &quot;Hello World&quot;</code></pre><p>Couple of differences to note are, <code>try</code> is not part of <code>Ruby</code> but <code>Rails</code>. Also<code>try</code>'s main purpose is protection against <code>nil</code> hence it doesn't execute theblock if receiver is <code>nil</code>.</p><pre><code class="language-ruby">irb&gt; nil.yield_self { |obj| &quot;Hello World&quot; }  =&gt; &quot;Hello World&quot;irb&gt; nil.try { |obj| &quot;Hello World&quot; }  =&gt; nil</code></pre><h4>What about <code>tap</code>?</h4><p><code>tap</code> also is similar to <code>yield_self</code>. It's part of Ruby itself. The onlydifference is the value that is returned. <code>tap</code> returns the receiver itselfwhile <code>yield_self</code> returns the output of the block.</p><pre><code class="language-ruby">irb&gt; &quot;Hello&quot;.yield_self { |str| str + &quot; World&quot; }  =&gt; &quot;Hello World&quot;irb&gt; &quot;Hello&quot;.tap { |str| str + &quot; World&quot; }  =&gt; &quot;Hello&quot;</code></pre><p>Overall, <code>yield_self</code> improves readability of the code by promoting chainingover nested function calls. Here is an example of both the styles.</p><pre><code class="language-ruby">irb&gt; add_greeting = -&gt; (str) { &quot;HELLO &quot; + str }irb&gt; to_upper = -&gt; (str) { str.upcase }# with new `yield_self`irb&gt; &quot;world&quot;.yield_self(&amp;to_upper)            .yield_self(&amp;add_greeting)  =&gt; &quot;HELLO WORLD&quot;# nested function callsirb&gt; add_greeting.call(to_upper.call(&quot;world&quot;))  =&gt; &quot;HELLO WORLD&quot;</code></pre><p><code>yield_self</code> is part of <code>Kernel</code> and hence it's available to all the objects.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 added delete_prefix and delete_suffix methods]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-5-added-delete_prefix-and-delete_suffix-methods"/>
      <updated>2017-11-28T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-5-added-delete_prefix-and-delete_suffix-methods</id>
      <content type="html"><![CDATA[<h4>Ruby 2.4</h4><p>Let's say that we have a string <code>Projects::CategoriesController</code> and we want toremove <code>Controller</code>. We can use<a href="https://ruby-doc.org/core-2.4.2/String.html#method-i-chomp">chomp</a> method.</p><pre><code class="language-ruby">irb&gt; &quot;Projects::CategoriesController&quot;.chomp(&quot;Controller&quot;)=&gt; &quot;Projects::Categories&quot;</code></pre><p>However if we want to remove <code>Projects::</code> from the string then there is nocorresponding method of <code>chomp</code>. We need to resort to<a href="https://ruby-doc.org/core-2.4.2/String.html#sub-method">sub</a>.</p><pre><code class="language-ruby">irb&gt; &quot;Projects::CategoriesController&quot;.sub(/Projects::/, '')=&gt; &quot;CategoriesController&quot;</code></pre><p><a href="https://bugs.ruby-lang.org/users/6938">Naotoshi Seo</a> did not like using regularexpression for such a simple task. He proposed that Ruby should have a methodfor taking care of such tasks.</p><p>Some of the names proposed were <code>remove_prefix</code>, <code>deprefix</code>, <code>lchomp</code>,<code>remove_prefix</code> and <code>head_chomp</code>.</p><p><a href="https://twitter.com/yukihiro_matz">Matz</a> suggested the name <code>delete_prefix</code> andthis method was born.</p><h4>Ruby 2.5.0-preview1</h4><pre><code class="language-ruby">irb&gt; &quot;Projects::CategoriesController&quot;.delete_prefix(&quot;Projects::&quot;)=&gt; &quot;CategoriesController&quot;</code></pre><p>Now in order to delete prefix we can use <code>delete_prefix</code> and to delete suffix wecould use <code>chomp</code>. This did not feel right. So for symmetry <code>delete_suffix</code> wasadded.</p><pre><code class="language-ruby">irb&gt; &quot;Projects::CategoriesController&quot;.delete_suffix(&quot;Controller&quot;)=&gt; &quot;Projects::Categories&quot;</code></pre><p>Read up on <a href="https://bugs.ruby-lang.org/issues/12694">this discussion</a> to learnmore about how elixir, go, python, and PHP deal with similar requirements.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 introduces Dir.children and Dir.each_child]]></title>
       <author><name>Mohit Natoo</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2_5-introduces-dir-children-and-dir-each_child"/>
      <updated>2017-11-21T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2_5-introduces-dir-children-and-dir-each_child</id>
      <content type="html"><![CDATA[<p><a href="https://ruby-doc.org/core-2.4.2/Dir.html#entries-method">Dir.entries</a> is amethod present in Ruby 2.4. It returns the output of shell command <code>ls -a</code> in anarray.</p><pre><code class="language-ruby">&gt; Dir.entries(&quot;/Users/john/Desktop/test&quot;)&gt; =&gt; [&quot;.&quot;, &quot;..&quot;, &quot;.config&quot;, &quot;program.rb&quot;, &quot;group.txt&quot;]&gt;</code></pre><p>We also have method<a href="https://ruby-doc.org/core-2.4.2/Dir.html#foreach-method">Dir.foreach</a> whichiterates and yields each value from the output of <code>ls -a</code> command to the block.</p><pre><code class="language-ruby">&gt; Dir.foreach(&quot;/Users/john/Desktop/test&quot;) { |child| puts child }&gt; .&gt; ..&gt; .config&gt; program.rb&gt; group.txt&gt; test2&gt;</code></pre><p>We can see that the output includes the directives for current directory andparent directory which are <code>&quot;.&quot;</code> and <code>&quot;..&quot;</code>.</p><p>When we want to have access only to the children files and directories, we donot need the <code>[&quot;.&quot;, &quot;..&quot;]</code> subarray.</p><p>This is a very common use case and we'll probably have to do something like<code>Dir.entries(path) - [&quot;.&quot;, &quot;..&quot;]</code> to achieve the desired output.</p><p>To overcome such issues,<a href="https://bugs.ruby-lang.org/issues/11302">Ruby 2.5 introduced Dir.children</a>. Itreturns the output of <code>ls -a</code> command without the directives for current andparent directories.</p><pre><code class="language-ruby">&gt; Dir.children(&quot;/Users/mohitnatoo/Desktop/test&quot;)&gt; =&gt; [&quot;.config&quot;, &quot;program.rb&quot;, &quot;group.txt&quot;]&gt;</code></pre><p>Additionally, we can use <code>Dir.each_child</code> method to avoid yielding current andparent directory directives while iterating,</p><pre><code class="language-ruby">&gt; Dir.each_child(&quot;/Users/mohitnatoo/Desktop/test&quot;) { |child| puts child }&gt; .config&gt; program.rb&gt; group.txt&gt; test2&gt;</code></pre><p>As noted in the <a href="https://bugs.ruby-lang.org/issues/11302">discussion</a> the nameswere chosen to match with existing methods<a href="https://ruby-doc.org/stdlib-2.4.2/libdoc/pathname/rdoc/Pathname.html#method-i-children">Pathname#children</a>and<a href="https://ruby-doc.org/core-2.4.2/Dir.html#foreach-method">Pathname#each_child</a>.</p><p>These additions seem like simple features. Well the issue was posted more thantwo years ago.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 allows rescue/else/ensure inside do/end blocks]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2.5-allows-rescue-inside-do-end-blocks"/>
      <updated>2017-10-24T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2.5-allows-rescue-inside-do-end-blocks</id>
      <content type="html"><![CDATA[<h4>Ruby 2.4</h4><pre><code class="language-ruby">irb&gt; array_from_user = [4, 2, 0, 1]  =&gt; [4, 2, 0, 1]irb&gt; array_from_user.each do |number|irb&gt;   p 10 / numberirb&gt; rescue ZeroDivisionError =&gt; exceptionirb&gt;   p exceptionirb&gt;   nextirb&gt; endSyntaxError: (irb):4: syntax error, unexpected keyword_rescue,expecting keyword_endrescue ZeroDivisionError =&gt; exception      ^</code></pre><p>Ruby 2.4 throws an error when we try to use rescue/else/ensure inside do/endblocks.</p><h4>Ruby 2.5.0-preview1</h4><pre><code class="language-ruby">irb&gt; array_from_user = [4, 2, 0, 1]  =&gt; [4, 2, 0, 1]irb&gt; array_from_user.each do |number|irb&gt;   p 10 / numberirb&gt; rescue ZeroDivisionError =&gt; exceptionirb&gt;   p exceptionirb&gt;   nextirb&gt; end25#&lt;ZeroDivisionError: divided by 0&gt;10 =&gt; [4, 2, 0, 1]</code></pre><p>Ruby 2.5 supports rescue/else/ensure inside do/end blocks.</p><p>Here is relevant <a href="https://github.com/ruby/ruby/commit/0ec889d7ed">commit</a> and<a href="https://bugs.ruby-lang.org/issues/12906">discussion</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.5 has removed top level constant lookup]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2.5-has-removed-top-level-constant-lookup"/>
      <updated>2017-10-18T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2.5-has-removed-top-level-constant-lookup</id>
      <content type="html"><![CDATA[<h4>Ruby 2.4</h4><pre><code class="language-ruby">irb&gt; class Projectirb&gt; end=&gt; nilirb&gt; class Categoryirb&gt; end=&gt; nilirb&gt; Project::Category(irb):5: warning: toplevel constant Category referenced by Project::Category =&gt; Category</code></pre><p>Ruby 2.4 returns the top level constant with a warning if it is unable to find aconstant in the specified scope.</p><p>This does not work well in cases where we need constants to be defined with samename at top level and also in the same scope.</p><h4>Ruby 2.5.0-preview1</h4><pre><code class="language-ruby">irb&gt; class Projectirb&gt; end=&gt; nilirb&gt; class Categoryirb&gt; end=&gt; nilirb&gt; Project::CategoryNameError: uninitialized constant Project::CategoryDid you mean?  Categoryfrom (irb):5</code></pre><p>Ruby 2.5 throws an error if it is unable to find a constant in the specifiedscope.</p><p>Here is the relevant <a href="https://github.com/ruby/ruby/commit/44a2576f79">commit</a>and <a href="https://bugs.ruby-lang.org/issues/11547">discussion</a>.</p>]]></content>
    </entry>
     </feed>