<?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-07-21T04:31:51+00:00</updated>
     <id>https://www.bigbinary.com/</id>
     <entry>
       <title><![CDATA[Ruby 2.4 has optimized enumerable min max methods]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-0-has-optimized-enumerable-min-max-methods"/>
      <updated>2017-09-28T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-0-has-optimized-enumerable-min-max-methods</id>
      <content type="html"><![CDATA[<p>Enumerables in Ruby have <code>min</code>, <code>max</code> and <code>minmax</code> comparison methods which arequite convenient to use.</p><pre><code class="language-ruby">(1..99).min #=&gt; 1(1..99).max #=&gt; 99(1..99).minmax #=&gt; [1, 99]</code></pre><p>In Ruby 2.4, <code>Enumurable#min</code>, <code>Enumurable#max</code><a href="https://github.com/ruby/ruby/commit/3dcd4b2a98e">methods</a> and<code>Enumurable#minmax</code> <a href="https://github.com/ruby/ruby/commit/9f44b77a18d">method</a>are now more optimized.</p><p>We would run the following benchmark snippet for both Ruby 2.3 and Ruby 2.4 andobserve the results</p><pre><code class="language-ruby">require 'benchmark/ips'Benchmark.ips do |bench|NUM1 = 1_000_000.times.map { rand }ENUM_MIN = Enumerable.instance_method(:min).bind(NUM1)ENUM_MAX = Enumerable.instance_method(:max).bind(NUM1)ENUM_MINMAX = Enumerable.instance_method(:minmax).bind(NUM1)bench.report('Enumerable#min') doENUM_MIN.callendbench.report('Enumerable#max') doENUM_MAX.callendbench.report('Enumerable#minmax') doENUM_MINMAX.callendend</code></pre><h4>Results for Ruby 2.3</h4><pre><code class="language-ruby">Warming up --------------------------------------Enumerable#min 1.000 i/100msEnumerable#max 1.000 i/100msEnumerable#minmax 1.000 i/100msCalculating -------------------------------------Enumerable#min 14.810 (13.5%) i/s - 73.000 in 5.072666sEnumerable#max 16.131 ( 6.2%) i/s - 81.000 in 5.052324sEnumerable#minmax 11.758 ( 0.0%) i/s - 59.000 in 5.026007s</code></pre><h4>Ruby 2.4</h4><pre><code class="language-ruby">Warming up --------------------------------------Enumerable#min 1.000 i/100msEnumerable#max 1.000 i/100msEnumerable#minmax 1.000 i/100msCalculating -------------------------------------Enumerable#min 18.091 ( 5.5%) i/s - 91.000 in 5.042064sEnumerable#max 17.539 ( 5.7%) i/s - 88.000 in 5.030514sEnumerable#minmax 13.086 ( 7.6%) i/s - 66.000 in 5.052537s</code></pre><p>From the above benchmark results, it can be seen that there has been animprovement in the run times for the methods.</p><p>Internally Ruby has changed the logic by which objects are compared, whichresults in these methods being optimized. You can have a look at the commits<a href="https://github.com/ruby/ruby/commit/9f44b77a18d">here</a> and<a href="https://github.com/ruby/ruby/commit/3dcd4b2a98e">here</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[CSV::Row#each etc. return enumerator when no block given]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/csv-row-each-and-delete-if-return-enumerator-when-no-block-given"/>
      <updated>2017-09-25T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/csv-row-each-and-delete-if-return-enumerator-when-no-block-given</id>
      <content type="html"><![CDATA[<p>In Ruby 2.3, These methods do not return enumerator when no block is given.</p><h3>Ruby 2.3</h3><pre><code class="language-ruby">CSV::Row.new(%w(banana mango), [1,2]).each #=&gt; #&lt;CSV::Row &quot;banana&quot;:1 &quot;mango&quot;:2&gt;CSV::Row.new(%w(banana mango), [1,2]).delete_if #=&gt; #&lt;CSV::Row &quot;banana&quot;:1 &quot;mango&quot;:2&gt;</code></pre><p>Some methods raise exception because of this behavior.</p><pre><code class="language-ruby">&gt; ruby -rcsv -e 'CSV::Table.new([CSV::Row.new(%w{banana mango}, [1, 2])]).by_col.each' #=&gt; /Users/sushant/.rbenv/versions/2.3.0/lib/ruby/2.3.0/csv.rb:850:in `block in each': undefined method `[]' for nil:NilClass (NoMethodError)  from /Users/sushant/.rbenv/versions/2.3.0/lib/ruby/2.3.0/csv.rb:850:in `each'  from /Users/sushant/.rbenv/versions/2.3.0/lib/ruby/2.3.0/csv.rb:850:in `each'  from -e:1:in `&lt;main&gt;'</code></pre><p>Ruby 2.4<a href="https://github.com/ruby/ruby/commit/b425d4f19ad9efaefcb1a767a6ea26e6d40e3985">fixed this issue</a>.</p><h3>Ruby 2.4</h3><pre><code class="language-ruby">CSV::Row.new(%w(banana mango), [1,2]).each #=&gt; #&lt;Enumerator: #&lt;CSV::Row &quot;banana&quot;:1 &quot;mango&quot;:2&gt;:each&gt;CSV::Row.new(%w(banana mango), [1,2]).delete_if #=&gt; #&lt;Enumerator: #&lt;CSV::Row &quot;banana&quot;:1 &quot;mango&quot;:2&gt;:delete_if&gt;</code></pre><p>As we can see, these methods now return an enumerator when no block is given.</p><p>In Ruby 2.4 following code will not raise any exception.</p><pre><code class="language-ruby">&gt; ruby -rcsv -e 'CSV::Table.new([CSV::Row.new(%w{banana mango}, [1, 2])]).by_col.each'</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 DateTime#to_time & Time#to_time keeps info]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/to-time-preserves-time-zone-info-in-ruby-2-4"/>
      <updated>2017-09-19T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/to-time-preserves-time-zone-info-in-ruby-2-4</id>
      <content type="html"><![CDATA[<p>In Ruby, <code>DateTime#to_time</code> and <code>Time#to_time</code> methods can be used to return aTime object.</p><p>In Ruby 2.3, these methods convert time into system timezone offset instead ofpreserving timezone offset of the receiver.</p><h3>Ruby 2.3</h3><pre><code class="language-ruby">&gt; datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z') #=&gt; #&lt;DateTime: 2017-05-16T10:15:30+09:00 ((2457890j,4530s,0n),+32400s,2299161j)&gt;&gt; datetime.to_time #=&gt; 2017-05-16 06:45:30 +0530&gt; time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00') #=&gt; 2017-05-16 10:15:30 +0900&gt; time.to_time #=&gt; 2017-05-16 06:45:30 +0530</code></pre><p>As you can see, <code>DateTime#to_time</code> and <code>Time#to_time</code> methods return time insystem timezone offset <code>+0530</code>.</p><p>Ruby 2.4 fixed<a href="https://github.com/ruby/ruby/commit/5f11a6eb6cca740b08384d1e4a68df643d98398c">DateTime#to_time</a>and<a href="https://github.com/ruby/ruby/commit/456523e2ede3073767fd8cb73cc4b159c3608890">Time#to_time</a>.</p><p>Now, <code>DateTime#to_time</code> and <code>Time#to_time</code> preserve receiver's timezone offsetinfo.</p><h3>Ruby 2.4</h3><pre><code class="language-ruby">&gt; datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z') #=&gt; #&lt;DateTime: 2017-05-16T10:15:30+09:00 ((2457890j,4530s,0n),+32400s,2299161j)&gt;&gt; datetime.to_time #=&gt; 2017-05-16 10:15:30 +0900&gt; time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00') #=&gt; 2017-05-16 10:15:30 +0900&gt; time.to_time #=&gt; 2017-05-16 10:15:30 +0900</code></pre><p>Since this is a breaking change for Rails application upgrading to ruby 2.4,Rails 4.2.8 built a compatibility layer by adding a<a href="https://github.com/rails/rails/commit/c9c5788a527b70d7f983e2b4b47e3afd863d9f48">config option</a>.<code>ActiveSupport.to_time_preserves_timezone</code> was added to control how <code>to_time</code>handles timezone offsets.</p><p>Here is an example of how application behaves when <code>to_time_preserves_timezone</code>is set to <code>false</code>.</p><pre><code class="language-ruby">&gt; ActiveSupport.to_time_preserves_timezone = false&gt; datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z') #=&gt; Tue, 16 May 2017 10:15:30 +0900&gt; datetime.to_time #=&gt; 2017-05-16 06:45:30 +0530&gt; time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00') #=&gt; 2017-05-16 10:15:30 +0900&gt; time.to_time #=&gt; 2017-05-16 06:45:30 +0530</code></pre><p>Here is an example of how application behaves when <code>to_time_preserves_timezone</code>is set to <code>true</code>.</p><pre><code class="language-ruby">&gt; ActiveSupport.to_time_preserves_timezone = true&gt; datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z') #=&gt; Tue, 16 May 2017 10:15:30 +0900&gt; datetime.to_time #=&gt; 2017-05-16 10:15:30 +0900&gt; time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00') #=&gt; 2017-05-16 10:15:30 +0900&gt; time.to_time #=&gt; 2017-05-16 10:15:30 +0900</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Avoid exception for dup on Integer]]></title>
       <author><name>Rohit Arolkar</name></author>
      <link href="https://www.bigbinary.com/blog/avoid-exceptions-for-dup-on-interger-and-similar-cases"/>
      <updated>2017-08-01T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/avoid-exceptions-for-dup-on-interger-and-similar-cases</id>
      <content type="html"><![CDATA[<p>Prior to Ruby 2.4, if we were to <code>dup</code> an <code>Integer</code>, it would fail with a<code>TypeError</code>.</p><pre><code class="language-ruby">&gt; 1.dupTypeError: can't dup Fixnumfrom (irb):1:in `dup'from (irb):1</code></pre><p>This was confusing because <code>Integer#dup</code> is actually implemented.</p><pre><code class="language-ruby">&gt; Integer.respond_to? :dup=&gt; true</code></pre><p>However, if we were to freeze an <code>Integer</code> it would fail silently.</p><pre><code class="language-ruby">&gt; 1.freeze=&gt; 1</code></pre><p>Ruby 2.4 has now included dup-ability for <code>Integer</code> as well.</p><pre><code class="language-ruby">&gt; 1.dup=&gt; 1</code></pre><p>In Ruby, some object types are immediate variables and therefore cannot beduped/cloned. Yet, there was no graceful way of averting the error thrown by thesanity check when we attempt to dup/clone them.</p><p>So now <code>Integer#dup</code> functions exactly the way <code>freeze</code> does -- fail silentlyand return the object itself. It makes sense because nothing about these objectscan be changed in the first place.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 no exception for objects converted to IPAddr]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-ip-addr-methods-do-not-throw-exception-for-objects-that-cant-be-converted-to-ipaddr"/>
      <updated>2017-06-21T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-ip-addr-methods-do-not-throw-exception-for-objects-that-cant-be-converted-to-ipaddr</id>
      <content type="html"><![CDATA[<p>In Ruby,<a href="https://docs.ruby-lang.org/en/2.4.0/IPAddr.html#method-i-3D-3D"><code>IPAddr#==</code></a>method is used to check whether two IP addresses are equal or not. Ruby also has<a href="https://docs.ruby-lang.org/en/2.4.0/IPAddr.html#method-i-3C-3D-3E"><code>IPAddr#&lt;=&gt;</code></a>method which is used to compare two IP addresses.</p><p>In Ruby 2.3, behavior of these methods was inconsistent. Let's see an example.</p><pre><code class="language-ruby"># Ruby 2.3&gt;&gt; IPAddr.new(&quot;1.2.1.3&quot;) == &quot;Some ip address&quot;=&gt; IPAddr::InvalidAddressError: invalid address</code></pre><p>But if the first argument is invalid IP address and second is valid IP address,then it would return <code>false</code>.</p><pre><code class="language-ruby"># Ruby 2.3&gt;&gt; &quot;Some ip address&quot; == IPAddr.new(&quot;1.2.1.3&quot;)=&gt; false</code></pre><p>The <code>&lt;=&gt;</code> method would raise exception in both the cases.</p><pre><code class="language-ruby"># Ruby 2.3&gt;&gt; &quot;Some ip address&quot; &lt;=&gt; IPAddr.new(&quot;1.2.1.3&quot;)=&gt; IPAddr::InvalidAddressError: invalid address&gt;&gt; IPAddr.new(&quot;1.2.1.3&quot;) &lt;=&gt; &quot;Some ip address&quot;=&gt; IPAddr::InvalidAddressError: invalid address</code></pre><p>In Ruby 2.4, <a href="https://bugs.ruby-lang.org/issues/12799">this issue</a> is<a href="https://github.com/ruby/ruby/pull/1435/files#diff-3504e08cf251c76a597c727011315dd1">fixed</a>for both the methods to return the result without raising exception, if theobjects being compared can't be converted to an IPAddr object.</p><pre><code class="language-ruby"># Ruby 2.4&gt;&gt; IPAddr.new(&quot;1.2.1.3&quot;) == &quot;Some ip address&quot;=&gt; false&gt;&gt; &quot;Some ip address&quot; == IPAddr.new(&quot;1.2.1.3&quot;)=&gt; false&gt;&gt; IPAddr.new(&quot;1.2.1.3&quot;) &lt;=&gt; &quot;Some ip address&quot;=&gt; nil&gt;&gt; &quot;Some ip address&quot; &lt;=&gt; IPAddr.new(&quot;1.2.1.3&quot;)=&gt; nil</code></pre><p>This might cause some backward compatibility if our code is expecting theexception which is no longer raised in Ruby 2.4.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 deprecated constants TRUE, FALSE & NIL]]></title>
       <author><name>Akshay Vishnoi</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-has-depecated-constants-true-false-and-nil"/>
      <updated>2017-06-19T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-has-depecated-constants-true-false-and-nil</id>
      <content type="html"><![CDATA[<p>Ruby has top level constants like <code>TRUE</code>, <code>FALSE</code> and <code>NIL</code>. These constants arejust synonyms for <code>true</code>, <code>false</code> and <code>nil</code> respectively.</p><p>In Ruby 2.4, these constants are<a href="https://bugs.ruby-lang.org/issues/12574">deprecated</a> and will be removed infuture version.</p><pre><code class="language-ruby"># Ruby 2.32.3.1 :001 &gt; TRUE =&gt; true2.3.1 :002 &gt; FALSE =&gt; false2.3.1 :003 &gt; NIL =&gt; nil</code></pre><pre><code class="language-ruby"># Ruby 2.42.4.0 :001 &gt; TRUE(irb):1: warning: constant ::TRUE is deprecated =&gt; true2.4.0 :002 &gt; FALSE(irb):2: warning: constant ::FALSE is deprecated =&gt; false2.4.0 :003 &gt; NIL(irb):3: warning: constant ::NIL is deprecated =&gt; nil</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 allows custom suffix of rotated log files]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-allows-to-customize-suffix-of-the-rotated-log-files"/>
      <updated>2017-06-15T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-allows-to-customize-suffix-of-the-rotated-log-files</id>
      <content type="html"><![CDATA[<p>In Ruby, The<a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/logger/rdoc/Logger.html#method-c-new">Logger</a>class can be used for rotating log files daily, weekly or monthly.</p><pre><code class="language-ruby">daily_logger = Logger.new('foo.log', 'daily')weekly_logger = Logger.new('foo.log', 'weekly')monthly_logger = Logger.new('foo.log', 'monthly')</code></pre><p>At the end of the specified period, Ruby will change the file extension of thelog file as follows:</p><pre><code class="language-ruby">foo.log.20170615</code></pre><p>The format of the suffix for the rotated log file is <code>%Y%m%d</code>. In Ruby 2.3,there was no way to customize this suffix format.</p><p>Ruby 2.4<a href="https://github.com/ruby/ruby/commit/2c6f15b1ad90af37d7e0eefff7b3f5262e0a4c0b">added the ability</a>to customize the suffix format by passing an extra argument<code>shift_period_suffix</code>.</p><pre><code class="language-ruby"># Ruby 2.4logger = Logger.new('foo.log', 'weekly', shift_period_suffix: '%d-%m-%Y')</code></pre><p>Now, suffix of the rotated log file will use the custom date format which wepassed.</p><pre><code class="language-ruby">foo.log.15-06-2017</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 Hash#transform_values & destructive version]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-added-hash-transform-values-and-its-destructive-version-from-active-support"/>
      <updated>2017-06-14T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-added-hash-transform-values-and-its-destructive-version-from-active-support</id>
      <content type="html"><![CDATA[<p>It is a common use case to transform the values of a hash.</p><pre><code class="language-ruby">{ a: 1, b: 2, c: 3 } =&gt; { a: 2, b: 4, c: 6 }{ a: &quot;B&quot;, c: &quot;D&quot;, e: &quot;F&quot; } =&gt; { a: &quot;b&quot;, c: &quot;d&quot;, e: &quot;f&quot; }</code></pre><p>We can transform the values of a hash destructively (i.e. modify the originalhash with new values) or non-destructively (i.e. return a new hash instead ofmodifying the original hash).</p><p>Prior to Ruby 2.4, we need to use following code to transform the values of ahash.</p><pre><code class="language-ruby"># Ruby 2.3 Non-destructive version&gt; hash = { a: 1, b: 2, c: 3 } #=&gt; {:a=&gt;1, :b=&gt;2, :c=&gt;3}&gt; hash.inject({}) { |h, (k, v)| h[k] = v * 2; h } #=&gt; {:a=&gt;2, :b=&gt;4, :c=&gt;6}&gt; hash #=&gt; {:a=&gt;1, :b=&gt;2, :c=&gt;3}&gt; hash = { a: &quot;B&quot;, c: &quot;D&quot;, e: &quot;F&quot; } #=&gt; {:a=&gt;&quot;B&quot;, :c=&gt;&quot;D&quot;, :e=&gt;&quot;F&quot;}&gt; hash.inject({}) { |h, (k, v)| h[k] = v.downcase; h } #=&gt; {:a=&gt;&quot;b&quot;, :c=&gt;&quot;d&quot;, :e=&gt;&quot;f&quot;}&gt; hash #=&gt; {:a=&gt;&quot;B&quot;, :c=&gt;&quot;D&quot;, :e=&gt;&quot;F&quot;}</code></pre><pre><code class="language-ruby"># Ruby 2.3 Destructive version&gt; hash = { a: 1, b: 2, c: 3 } #=&gt; {:a=&gt;1, :b=&gt;2, :c=&gt;3}&gt; hash.each { |k, v| hash[k] = v * 2 } #=&gt; {:a=&gt;2, :b=&gt;4, :c=&gt;6}&gt; hash #=&gt; {:a=&gt;2, :b=&gt;4, :c=&gt;6}&gt; hash = { a: &quot;B&quot;, c: &quot;D&quot;, e: &quot;F&quot; } #=&gt; {:a=&gt;&quot;B&quot;, :c=&gt;&quot;D&quot;, :e=&gt;&quot;F&quot;}&gt; hash.each { |k, v| hash[k] = v.downcase } #=&gt; {:a=&gt;&quot;b&quot;, :c=&gt;&quot;d&quot;, :e=&gt;&quot;f&quot;}&gt; hash #=&gt; {:a=&gt;&quot;b&quot;, :c=&gt;&quot;d&quot;, :e=&gt;&quot;f&quot;}</code></pre><h2>transform_values and transform_values! from Active Support</h2><p>Active Support has already implemented handy methods<a href="https://github.com/rails/rails/commit/b2cf8b251aac39c1e3ce71bc1de34a2ce5ef52b1">Hash#transform_values and Hash#transform_values!</a>to transform hash values.</p><p>Now, Ruby 2.4 has also implemented<a href="https://github.com/ruby/ruby/commit/ea5184b939ec3dbdcbd7013da350b8dcb6ca6107">Hash#map_v and Hash#map_v!</a>and then renamed to<a href="https://github.com/ruby/ruby/commit/eaa0a27f6149a9afa2b29729307ff9cc7b0bc95f">Hash#transform_values and Hash#transform_values!</a>for the same purpose.</p><pre><code class="language-ruby"># Ruby 2.4 Non-destructive version&gt; hash = { a: 1, b: 2, c: 3 } #=&gt; {:a=&gt;1, :b=&gt;2, :c=&gt;3}&gt; hash.transform_values { |v| v * 2 } #=&gt; {:a=&gt;2, :b=&gt;4, :c=&gt;6}&gt; hash #=&gt; {:a=&gt;1, :b=&gt;2, :c=&gt;3}&gt; hash = { a: &quot;B&quot;, c: &quot;D&quot;, e: &quot;F&quot; } #=&gt; {:a=&gt;&quot;B&quot;, :c=&gt;&quot;D&quot;, :e=&gt;&quot;F&quot;}&gt; hash.transform_values(&amp;:downcase) #=&gt; {:a=&gt;&quot;b&quot;, :c=&gt;&quot;d&quot;, :e=&gt;&quot;f&quot;}&gt; hash #=&gt; {:a=&gt;&quot;B&quot;, :c=&gt;&quot;D&quot;, :e=&gt;&quot;F&quot;}</code></pre><pre><code class="language-ruby"># Ruby 2.4 Destructive version&gt; hash = { a: 1, b: 2, c: 3 } #=&gt; {:a=&gt;1, :b=&gt;2, :c=&gt;3}&gt; hash.transform_values! { |v| v * 2 } #=&gt; {:a=&gt;2, :b=&gt;4, :c=&gt;6}&gt; hash #=&gt; {:a=&gt;2, :b=&gt;4, :c=&gt;6}&gt; hash = { a: &quot;B&quot;, c: &quot;D&quot;, e: &quot;F&quot; } #=&gt; {:a=&gt;&quot;B&quot;, :c=&gt;&quot;D&quot;, :e=&gt;&quot;F&quot;}&gt; hash.transform_values!(&amp;:downcase) #=&gt; {:a=&gt;&quot;b&quot;, :c=&gt;&quot;d&quot;, :e=&gt;&quot;f&quot;}&gt; hash #=&gt; {:a=&gt;&quot;b&quot;, :c=&gt;&quot;d&quot;, :e=&gt;&quot;f&quot;}</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Binding irb - Runtime Invocation for IRB]]></title>
       <author><name>Rohit Arolkar</name></author>
      <link href="https://www.bigbinary.com/blog/binding-irb"/>
      <updated>2017-04-18T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/binding-irb</id>
      <content type="html"><![CDATA[<p>It's very common to see a ruby programmer write a few <code>puts</code> or <code>p</code> statements,either for debugging or for knowing the value of variables.</p><p><a href="https://github.com/pry/pry">pry</a> did make our lives easier with the usage of<code>binding.pry</code>. However, it was still a bit of an inconvenience to have itinstalled at runtime, while working with the <code>irb</code>.</p><p>Ruby 2.4 has now introduced <code>binding.irb</code>. By simply adding <code>binding.irb</code> to ourcode we can open an IRB session.</p><pre><code class="language-ruby">class ConvolutedProcessdef do_something@variable = 10    binding.irb    # opens a REPL hereendendirb(main):029:0\* ConvolutedProcess.new.do_somethingirb(#&lt;ConvolutedProcess:0x007fc55c827f48&gt;):001:0&gt; @variable=&gt; 10</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 has added additional parameters for Logger#new]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-has-added-additional-parameters-for-logger-new"/>
      <updated>2017-04-10T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-has-added-additional-parameters-for-logger-new</id>
      <content type="html"><![CDATA[<p>The<a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/logger/rdoc/Logger.html#method-c-new">Logger</a>class in Ruby provides a simple but sophisticated logging utility.</p><p>After creating the logger object we need to set its level.</p><h3>Ruby 2.3</h3><pre><code class="language-ruby">require 'logger'logger = Logger.new(STDOUT)logger.level = Logger::INFO</code></pre><p>If we are working with <code>ActiveRecord::Base.logger</code>, then same code would looksomething like this.</p><pre><code class="language-ruby">require 'logger'ActiveRecord::Base.logger = Logger.new(STDOUT)ActiveRecord::Base.logger.level = Logger::INFO</code></pre><p>As we can see in the both the cases we need to set the level separately afterinstantiating the object.</p><h3>Ruby 2.4</h3><p>In Ruby 2.4, <code>level</code> can now be specified in the constructor.</p><pre><code class="language-ruby">#ruby 2.4require 'logger'logger = Logger.new(STDOUT, level: Logger::INFO)# let's verify itlogger.level      #=&gt; 1</code></pre><p>Similarly, other options such as <code>progname</code>, <code>formatter</code> and <code>datetime_format</code>,which prior to Ruby 2.4 had to be explicitly set, can now be set during theinstantiation.</p><pre><code class="language-ruby">#ruby 2.3require 'logger'logger = Logger.new(STDOUT)logger.level = Logger::INFOlogger.progname = 'bigbinary'logger.datetime_format = '%Y-%m-%d %H:%M:%S'logger.formatter = proc do |severity, datetime, progname, msg|  &quot;#{severity} #{datetime} ==&gt; App: #{progname}, Message: #{msg}\n&quot;endlogger.info(&quot;Program started...&quot;)#=&gt; INFO 2017-03-16 18:43:58 +0530 ==&gt; App: bigbinary, Message: Program started...</code></pre><p>Here is same stuff in Ruby 2.4.</p><pre><code class="language-ruby">#ruby 2.4require 'logger'logger = Logger.new(STDOUT,  level: Logger::INFO,  progname: 'bigbinary',  datetime_format: '%Y-%m-%d %H:%M:%S',  formatter: proc do |severity, datetime, progname, msg|    &quot;#{severity} #{datetime} ==&gt; App: #{progname}, Message: #{msg}\n&quot;  end)logger.info(&quot;Program started...&quot;)#=&gt; INFO 2017-03-16 18:47:39 +0530 ==&gt; App: bigbinary, Message: Program started...</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 has default basename for Tempfile#create]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-has-default-basename-for-tempfile-create"/>
      <updated>2017-04-04T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-has-default-basename-for-tempfile-create</id>
      <content type="html"><![CDATA[<h3>Tempfile class</h3><p><a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/tempfile/rdoc/Tempfile.html">Tempfile</a>is used for managing temporary files in Ruby. A Tempfile object creates atemporary file with a unique filename. It behaves just like a File object, andtherefore we can perform all the usual file operations on it.</p><h3>Why Tempfile when we can use File</h3><p>These days it is common to store file on services like S3. Let's say that wehave a <code>users.csv</code> file on S3. Working with this file remotely is problematic.In such cases it is desirable to download the file on local machine formanipulation. After the work is done then file should be deleted. Tempfile isideal for such cases.</p><h3>Basename for tempfile</h3><p>If we want to create a temporary file then we needed to pass parameter to itprior to Ruby 2.3.</p><pre><code class="language-ruby">require 'tempfile'file = Tempfile.new('bigbinary')#=&gt; #&lt;Tempfile:/var/folders/jv/fxkfk9_10nb_964rvrszs2540000gn/T/bigbinary-20170304-10828-1w02mqi&gt;</code></pre><p>As we can see above the generated file name begins with &quot;bigbinary&quot; word.</p><p>Since Tempfile ensures that the generate filename will always be unique thepoint of passing the argument is meaningless. Ruby doc calls this passing&quot;basename&quot;.</p><p>So in Ruby 2.3.0 it was <a href="https://github.com/ruby/ruby/pull/523">decided</a> thatthe basename parameter was meaningless for <code>Tempfile#new</code> and an empty stringwill be the default value.</p><pre><code class="language-ruby">require 'tempfile'file = Tempfile.new#=&gt; #&lt;Tempfile:/var/folders/jv/fxkfk9_10nb_964rvrszs2540000gn/T/20170304-10828-1v855bf&gt;</code></pre><p>But the same was not implemented for <code>Tempfile#create</code>.</p><pre><code class="language-ruby"># Ruby 2.3.0require 'tempfile'Tempfile.create do |f|  f.write &quot;hello&quot;endArgumentError: wrong number of arguments (given 0, expected 1..2)</code></pre><p>This was <a href="https://bugs.ruby-lang.org/issues/11965">fixed</a> in Ruby 2.4. So nowthe basename parameter for <code>Tempfile.create</code> is set to empty string by default,to keep it consistent with the <code>Tempfile#new</code> method.</p><pre><code class="language-ruby"># Ruby 2.4require 'tempfile'Tempfile.create do |f|  f.write &quot;hello&quot;end=&gt; 5</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[New arguments support for float & integer modifiers]]></title>
       <author><name>Abhishek Jain</name></author>
      <link href="https://www.bigbinary.com/blog/new-ndigits-arguments-supported-for-float-modifiers-in-ruby-2-4"/>
      <updated>2017-03-28T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/new-ndigits-arguments-supported-for-float-modifiers-in-ruby-2-4</id>
      <content type="html"><![CDATA[<p>In Ruby, there are many methods available which help us to modify a float orinteger value.</p><h3>Ruby 2.3.x</h3><p>In the previous versions of Ruby, we could use methods such as <code>floor</code>, <code>ceil</code>and <code>truncate</code> in following ways.</p><pre><code class="language-ruby">5.54.floor          #=&gt; 55.54.ceil           #=&gt; 65.54.truncate       #=&gt; 5</code></pre><p>Providing an argument to these methods would result in <code>ArgumentError</code>exception.</p><h3>Ruby 2.4</h3><p>Ruby community decided to come up with an option to<a href="https://bugs.ruby-lang.org/issues/12245">add precision argument</a> .</p><p>The precision argument, which can be negative, helps us to get result to therequired precision to either side of the decimal point.</p><p>The default value for the precision argument is 0.</p><pre><code class="language-ruby">876.543.floor(-2)       #=&gt; 800876.543.floor(-1)       #=&gt; 870876.543.floor           #=&gt; 876876.543.floor(1)        #=&gt; 876.5876.543.floor(2)        #=&gt; 876.54876.543.ceil(-2)        #=&gt; 900876.543.ceil(-1)        #=&gt; 880876.543.ceil            #=&gt; 877876.543.ceil(1)         #=&gt; 876.6876.543.ceil(2)         #=&gt; 876.55876.543.truncate(-2)    #=&gt; 800876.543.truncate(-1)    #=&gt; 870876.543.truncate        #=&gt; 876876.543.truncate(1)     #=&gt; 876.5876.543.truncate(2)     #=&gt; 876.54</code></pre><p>These methods all work the same on Integer as well.</p><pre><code class="language-ruby">5.floor(2)              #=&gt; 5.05.ceil(2)               #=&gt; 5.05.truncate(2)           #=&gt; 5.0</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 adds Enumerable#uniq & Enumerable::Lazy#uniq]]></title>
       <author><name>Mohit Natoo</name></author>
      <link href="https://www.bigbinary.com/blog/enumerable-uniq-and-enumerable-lazy-uniq-part-of-ruby-2-4"/>
      <updated>2017-03-21T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/enumerable-uniq-and-enumerable-lazy-uniq-part-of-ruby-2-4</id>
      <content type="html"><![CDATA[<p>In Ruby, we commonly use <code>uniq</code> method on an array to fetch the collection ofall unique elements. But there may be cases where we might need elements in ahash by virtue of uniqueness of its values.</p><p>Let's consider an example of countries that have hosted the Olympics. We onlywant to know when was the first time a country hosted it.</p><pre><code class="language-ruby"># given object{ 1896 =&gt; 'Athens',  1900 =&gt; 'Paris',  1904 =&gt; 'Chicago',  1906 =&gt; 'Athens',  1908 =&gt; 'Rome' }# expected outcome{ 1896 =&gt; 'Athens',  1900 =&gt; 'Paris',  1904 =&gt; 'Chicago',  1908 =&gt; 'Rome' }</code></pre><p>One way to achieve this is to have a collection of unique country names and thencheck if that value is already taken while building the result.</p><pre><code class="language-ruby">olympics ={ 1896 =&gt; 'Athens',  1900 =&gt; 'Paris',  1904 =&gt; 'Chicago',  1906 =&gt; 'Athens',  1908 =&gt; 'Rome' }unique_nations = olympics.values.uniqolympics.select{ |year, country| !unique_nations.delete(country).nil? }#=&gt; {1896=&gt;&quot;Athens&quot;, 1900=&gt;&quot;Paris&quot;, 1904=&gt;&quot;Chicago&quot;, 1908=&gt;&quot;Rome&quot;}</code></pre><p>As we can see, the above code requires constructing an additional array<code>unique_nations</code>.</p><p>In processing larger data, loading an array of considerably big size in memoryand then carrying out further processing on it, may result in performance andmemory issues.</p><p>In Ruby 2.4, <code>Enumerable</code> class introduces <code>uniq</code><a href="https://bugs.ruby-lang.org/issues/11090">method</a> that collects unique elementswhile iterating over the enumerable object.</p><p>The usage is similar to that of Array#uniq. Uniqueness can be determined by theelements themselves or by a value yielded by the block passed to the <code>uniq</code>method.</p><pre><code class="language-ruby">olympics = {1896 =&gt; 'Athens', 1900 =&gt; 'Paris', 1904 =&gt; 'Chicago', 1906 =&gt; 'Athens', 1908 =&gt; 'Rome'}olympics.uniq { |year, country| country }.to_h#=&gt; {1896=&gt;&quot;Athens&quot;, 1900=&gt;&quot;Paris&quot;, 1904=&gt;&quot;Chicago&quot;, 1908=&gt;&quot;Rome&quot;}</code></pre><p>Similar method is also implemented in <code>Enumerable::Lazy</code> class. Hence we can nowcall <code>uniq</code> on lazy enumerables.</p><pre><code class="language-ruby">(1..Float::INFINITY).lazy.uniq { |x| (x**2) % 10 }.first(6)#=&gt; [1, 2, 3, 4, 5, 10]</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 optimized lstrip & strip for ASCII strings]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-has-optimized-lstrip-and-strip-methods"/>
      <updated>2017-03-14T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-has-optimized-lstrip-and-strip-methods</id>
      <content type="html"><![CDATA[<p>Ruby has <code>lstrip</code> and <code>rstrip</code> methods which can be used to remove leading andtrailing whitespaces respectively from a string.</p><p>Ruby also has <code>strip</code> method which is a combination of lstrip and rstrip and canbe used to remove both, leading and trailing whitespaces, from a string.</p><pre><code class="language-ruby">&quot;    Hello World    &quot;.lstrip    #=&gt; &quot;Hello World    &quot;&quot;    Hello World    &quot;.rstrip    #=&gt; &quot;    Hello World&quot;&quot;    Hello World    &quot;.strip     #=&gt; &quot;Hello World&quot;</code></pre><p>Prior to Ruby 2.4, the <code>rstrip</code> method was optimized for performance, but the<code>lstrip</code> and <code>strip</code> were somehow missed. In Ruby 2.4, <code>String#lstrip</code> and<code>String#strip</code> methods too have been<a href="https://bugs.ruby-lang.org/issues/12788">optimized</a> to get the performancebenefit of <code>String#rstrip</code> .</p><p>Let's run following snippet in Ruby 2.3 and Ruby 2.4 to benchmark and comparethe performance improvement.</p><pre><code class="language-ruby">require 'benchmark/ips'Benchmark.ips do |bench|  str1 = &quot; &quot; * 10_000_000 + &quot;hello world&quot; + &quot; &quot; * 10_000_000  str2 = str1.dup  str3 = str1.dup  bench.report('String#lstrip') do    str1.lstrip  end  bench.report('String#rstrip') do    str2.rstrip  end  bench.report('String#strip') do    str3.strip  endend</code></pre><h4>Result for Ruby 2.3</h4><pre><code class="language-ruby">Warming up --------------------------------------       String#lstrip     1.000  i/100ms       String#rstrip     8.000  i/100ms        String#strip     1.000  i/100msCalculating -------------------------------------       String#lstrip     10.989  ( 0.0%) i/s -     55.000  in   5.010903s       String#rstrip     92.514  ( 5.4%) i/s -    464.000  in   5.032208s        String#strip     10.170  ( 0.0%) i/s -     51.000  in   5.022118s</code></pre><h4>Result for Ruby 2.4</h4><pre><code class="language-ruby">Warming up --------------------------------------       String#lstrip    14.000  i/100ms       String#rstrip     8.000  i/100ms        String#strip     6.000  i/100msCalculating -------------------------------------       String#lstrip    143.424  ( 4.2%) i/s -    728.000  in   5.085311s       String#rstrip     89.150  ( 5.6%) i/s -    448.000  in   5.041301s        String#strip     67.834  ( 4.4%) i/s -    342.000  in   5.051584s</code></pre><p>From the above results, we can see that in Ruby 2.4, <code>String#lstrip</code> is around14x faster while <code>String#strip</code> is around 6x faster. <code>String#rstrip</code> asexpected, has nearly the same performance as it was already optimized inprevious versions.</p><h3>Performance remains same for multi-byte strings</h3><p>Strings can have single byte or multi-byte characters.</p><p>For example <code>L Hello World</code> is a multi-byte string because of the presence of<code></code> which is a multi-byte character.</p><pre><code class="language-ruby">'e'.bytesize        #=&gt; 1''.bytesize        #=&gt; 2</code></pre><p>Let's do performance benchmarking with string <code>L hello world</code> instead of<code>hello world</code>.</p><h4>Result for Ruby 2.3</h4><pre><code class="language-ruby">Warming up --------------------------------------       String#lstrip     1.000  i/100ms       String#rstrip     1.000  i/100ms        String#strip     1.000  i/100msCalculating -------------------------------------       String#lstrip     11.147  ( 9.0%) i/s -     56.000  in   5.034363s       String#rstrip      8.693  ( 0.0%) i/s -     44.000  in   5.075011s        String#strip      5.020  ( 0.0%) i/s -     26.000  in   5.183517s</code></pre><h4>Result for Ruby 2.4</h4><pre><code class="language-ruby">Warming up --------------------------------------       String#lstrip     1.000  i/100ms       String#rstrip     1.000  i/100ms        String#strip     1.000  i/100msCalculating -------------------------------------       String#lstrip     10.691  ( 0.0%) i/s -     54.000  in   5.055101s       String#rstrip      9.524  ( 0.0%) i/s -     48.000  in   5.052678s        String#strip      4.860  ( 0.0%) i/s -     25.000  in   5.152804s</code></pre><p>As we can see, the performance for multi-byte strings is almost the same acrossRuby 2.3 and Ruby 2.4.</p><h4>Explanation</h4><p>The optimization introduced is related to how the strings are parsed to detectfor whitespaces. Checking for whitespaces in multi-byte string requires anadditional overhead. So the <a href="https://bugs.ruby-lang.org/issues/12788">patch</a>adds an initial condition to check if the string is a single byte string, and ifso, processes it separately.</p><p>In most of the cases, the strings are single byte so the performance improvementwould be visible and helpful.</p>]]></content>
    </entry><entry>
       <title><![CDATA[IO#readlines now accepts chomp flag as an argument]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/io-readlines-now-accepts-chomp-flag-as-an-argument"/>
      <updated>2017-03-07T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/io-readlines-now-accepts-chomp-flag-as-an-argument</id>
      <content type="html"><![CDATA[<p>Consider the following file which needs to be read in Ruby. We can use the<code>IO#readlines</code> method to get the lines in an array.</p><pre><code class="language-plaintext"># lotr.txtThree Rings for the Elven-kings under the sky,Seven for the Dwarf-lords in their halls of stone,Nine for Mortal Men doomed to die,One for the Dark Lord on his dark throneIn the Land of Mordor where the Shadows lie.</code></pre><h3>Ruby 2.3</h3><pre><code class="language-ruby">IO.readlines('lotr.txt')#=&gt; [&quot;Three Rings for the Elven-kings under the sky,\n&quot;, &quot;Seven for the Dwarf-lords in their halls of stone,\n&quot;, &quot;Nine for Mortal Men doomed to die,\n&quot;, &quot;One for the Dark Lord on his dark throne\n&quot;, &quot;In the Land of Mordor where the Shadows lie.&quot;]</code></pre><p>As we can see, the lines in the array have a <code>\n</code>, newline character, which isnot skipped while reading the lines. The newline character needs to be choppedin most of the cases. Prior to Ruby 2.4, it could be done in the following way.</p><pre><code class="language-ruby">IO.readlines('lotr.txt').map(&amp;:chomp)#=&gt; [&quot;Three Rings for the Elven-kings under the sky,&quot;, &quot;Seven for the Dwarf-lords in their halls of stone,&quot;, &quot;Nine for Mortal Men doomed to die,&quot;, &quot;One for the Dark Lord on his dark throne&quot;, &quot;In the Land of Mordor where the Shadows lie.&quot;]</code></pre><h3>Ruby 2.4</h3><p>Since it was a common requirement, Ruby team decided to<a href="https://bugs.ruby-lang.org/issues/12553">add</a> an optional parameter to the<code>readlines</code> method. So the same can now be achieved in Ruby 2.4 in the followingway.</p><pre><code class="language-ruby">IO.readlines('lotr.txt', chomp: true)#=&gt; [&quot;Three Rings for the Elven-kings under the sky,&quot;, &quot;Seven for the Dwarf-lords in their halls of stone,&quot;, &quot;Nine for Mortal Men doomed to die,&quot;, &quot;One for the Dark Lord on his dark throne&quot;, &quot;In the Land of Mordor where the Shadows lie.&quot;]</code></pre><p>Additionally, <code>IO#gets</code>, <code>IO#readline</code>, <code>IO#each_line</code>, <code>IO#foreach</code> methodsalso have been modified to accept an optional chomp flag.</p>]]></content>
    </entry><entry>
       <title><![CDATA[open-uri in Ruby 2.4 allows http to https redirection]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/open-uri-in-ruby-2-4-allows-http-to-https-redirection"/>
      <updated>2017-03-02T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/open-uri-in-ruby-2-4-allows-http-to-https-redirection</id>
      <content type="html"><![CDATA[<p>In Ruby 2.3, if the argument to <code>open-uri</code> is http and the host redirects tohttps , then <code>open-uri</code> would throw an error.</p><pre><code class="language-ruby">&gt; require 'open-uri'&gt; open('http://www.google.com/gmail')RuntimeError: redirection forbidden: http://www.google.com/gmail -&gt; https://www.google.com/gmail/</code></pre><p>To get around this issue, we could use<a href="https://github.com/open-uri-redirections/open_uri_redirections">open_uri_redirections</a>gem.</p><pre><code class="language-ruby">&gt; require 'open-uri'&gt; require 'open_uri_redirections'&gt; open('http://www.google.com/gmail/', :allow_redirections =&gt; :safe)=&gt; #&lt;Tempfile:/var/folders/jv/fxkfk9_10nb_964rvrszs2540000gn/T/open-uri20170228-41042-2fffoa&gt;</code></pre><h3>Ruby 2.4</h3><p>In Ruby 2.4, this issue is <a href="https://bugs.ruby-lang.org/issues/859">fixed</a>. Sonow http to https redirection is possible using open-uri.</p><pre><code class="language-ruby">&gt; require 'open-uri'&gt; open('http://www.google.com/gmail')=&gt; #&lt;Tempfile:/var/folders/jv/fxkfk9_10nb_964rvrszs2540000gn/T/open-uri20170228-41077-1bkm1dv&gt;</code></pre><p>Note that redirection from https to http will raise an error, like it did inprevious versions, since that has possible security concerns.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 now has Dir.empty? and File.empty? methods]]></title>
       <author><name>Ratnadeep Deshmane</name></author>
      <link href="https://www.bigbinary.com/blog/dir-emtpy-included-in-ruby-2-4"/>
      <updated>2017-02-28T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/dir-emtpy-included-in-ruby-2-4</id>
      <content type="html"><![CDATA[<p>In Ruby, to check if a given directory is empty or not, we check it as</p><pre><code class="language-ruby">Dir.entries(&quot;/usr/lib&quot;).size == 2       #=&gt; falseDir.entries(&quot;/home&quot;).size == 2          #=&gt; true</code></pre><p>Every directory in Unix filesystem contains at least two entries. These are<code>.</code>(current directory) and <code>..</code>(parent directory).</p><p>Hence, the code above checks if there are only two entries and if so, consider adirectory empty.</p><p>Again, this code only works for UNIX filesystems and fails on Windows machines,as Windows directories don't have <code>.</code> or <code>..</code>.</p><h2>Dir.empty?</h2><p>Considering all this, Ruby has finally<a href="https://bugs.ruby-lang.org/issues/10121">included</a> a new method <code>Dir.empty?</code>that takes directory path as argument and returns boolean as an answer.</p><p>Here is an example.</p><pre><code class="language-ruby">Dir.empty?('/Users/rtdp/Documents/posts')   #=&gt; true</code></pre><p>Most importantly this method works correctly in all platforms.</p><h2>File.empty?</h2><p>To check if a file is empty, Ruby has <code>File.zero?</code> method. This checks if thefile exists and has zero size.</p><pre><code class="language-ruby">File.zero?('/Users/rtdp/Documents/todo.txt')    #=&gt; true</code></pre><p>After introducing <code>Dir.empty?</code> it makes sense to<a href="https://bugs.ruby-lang.org/issues/9969">add</a> <code>File.empty?</code> as an alias to<code>File.zero?</code></p><pre><code class="language-ruby">File.empty?('/Users/rtdp/Documents/todo.txt')    #=&gt; true</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 Integer#digits extract digits in place-value]]></title>
       <author><name>Rohit Kumar</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-implements-integer-digits-for-extracting-digits-in-place-value-notation"/>
      <updated>2017-02-23T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-implements-integer-digits-for-extracting-digits-in-place-value-notation</id>
      <content type="html"><![CDATA[<p>If we want to extract all the digits of an integer<a href="https://en.wikipedia.org/wiki/Positional_notation">from right to left</a>, thenewly added <a href="https://bugs.ruby-lang.org/issues/12447">Integer#digits</a> methodwill come in handy.</p><pre><code class="language-ruby">567321.digits#=&gt; [1, 2, 3, 7, 6, 5]567321.digits[3]#=&gt; 7</code></pre><p>We can also supply a different base as an argument.</p><pre><code class="language-ruby">0123.digits(8)#=&gt; [3, 2, 1]0xabcdef.digits(16)#=&gt; [15, 14, 13, 12, 11, 10]</code></pre><h4>Use case of digits</h4><p>We can use <code>Integer#digits</code> to sum all the digits in an integer.</p><pre><code class="language-ruby">123.to_s.chars.map(&amp;:to_i).sum#=&gt; 6123.digits.sum#=&gt; 6</code></pre><p>Also while calculating checksums like<a href="https://en.wikipedia.org/wiki/Luhn_algorithm">Luhn</a> and<a href="https://en.wikipedia.org/wiki/Verhoeff_algorithm">Verhoeff</a>, <code>Integer#digits</code>will help in reducing string allocation.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 adds compare by identity functionality]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-adds-compare-by-identity-functionality-for-sets"/>
      <updated>2016-12-29T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-adds-compare-by-identity-functionality-for-sets</id>
      <content type="html"><![CDATA[<p>In Ruby, <code>Object#equal?</code> method is used to compare two objects by theiridentity, that is, the two objects are exactly the same or not. Ruby also has<code>Object#eql?</code> method which returns true if two objects have the same value.</p><p>For example:</p><pre><code class="language-ruby">str1 = &quot;Sample string&quot;str2 = str1.dupstr1.eql?(str2) #=&gt; truestr1.equal?(str2) #=&gt; false</code></pre><p>We can see that object ids of the objects are not same.</p><pre><code class="language-ruby">str1.object_id #=&gt; 70334175057920str2.object_id #=&gt; 70334195702480</code></pre><p>In ruby, <a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html">Set</a> doesnot allow duplicate items in its collection. To determine if two items are equalor not in a <code>Set</code> ruby uses <code>Object#eql?</code> and not <code>Object#equal?</code>.</p><p>So if we want to add two different objects with the same values in a set, thatwould not have been possible prior to Ruby 2.4 .</p><h3>Ruby 2.3</h3><pre><code class="language-ruby">require 'set'set = Set.new #=&gt; #&lt;Set: {}&gt;str1 = &quot;Sample string&quot; #=&gt; &quot;Sample string&quot;str2 = str1.dup #=&gt; &quot;Sample string&quot;set.add(str1) #=&gt; #&lt;Set: {&quot;Sample string&quot;}&gt;set.add(str2) #=&gt; #&lt;Set: {&quot;Sample string&quot;}&gt;</code></pre><p>But with the new<a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html#method-i-compare_by_identity">Set#compare_by_identity method introduced in Ruby 2.4</a>,sets can now compare its values using <code>Object#equal?</code> and check for the exactsame objects.</p><h3>Ruby 2.4</h3><pre><code class="language-ruby">require 'set'set = Set.new.compare_by_identity #=&gt; #&lt;Set: {}&gt;str1 = &quot;Sample string&quot; #=&gt; &quot;Sample string&quot;str2 = str1.dup #=&gt; &quot;Sample string&quot;set.add(str1) #=&gt; #&lt;Set: {&quot;Sample string&quot;}&gt;set.add(str2) #=&gt; #&lt;Set: {&quot;Sample string&quot;, &quot;Sample string&quot;}&gt;</code></pre><h2>Set#compare_by_identity?</h2><p>Ruby 2.4 also provides the<a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html#method-i-compare_by_identity-3F">compare_by_identity? method</a>to know if the set will compare its elements by their identity.</p><pre><code class="language-ruby">require 'set'set1= Set.new #=&gt; #&lt;Set: {}&gt;set2= Set.new.compare_by_identity #=&gt; #&lt;Set: {}&gt;set1.compare_by_identity? #=&gt; falseset2.compare_by_identity? #=&gt; true</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 MatchData#values_at]]></title>
       <author><name>Rohit Kumar</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2.4-adds-matchdata-values-at-for-extracting-named-and-positional-capture-groups"/>
      <updated>2016-12-21T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2.4-adds-matchdata-values-at-for-extracting-named-and-positional-capture-groups</id>
      <content type="html"><![CDATA[<h3>Ruby 2.3</h3><p>We can use <code>MatchData#[]</code> to extract named capture and positional capturegroups.</p><pre><code class="language-ruby">pattern=/(?&lt;number&gt;\d+) (?&lt;word&gt;\w+)/pattern.match('100 thousand')[:number]#=&gt; &quot;100&quot;pattern=/(\d+) (\w+)/pattern.match('100 thousand')[2]#=&gt; &quot;thousand&quot;</code></pre><p>Positional capture groups could also be extracted using <code>MatchData#values_at</code>.</p><pre><code class="language-ruby">pattern=/(\d+) (\w+)/pattern.match('100 thousand').values_at(2)#=&gt; [&quot;thousand&quot;]</code></pre><h3>Changes in Ruby 2.4</h3><p>In Ruby 2.4, we can pass string or symbol to extract named capture groups tomethod <code>#values_at</code>.</p><pre><code class="language-ruby">pattern=/(?&lt;number&gt;\d+) (?&lt;word&gt;\w+)/pattern.match('100 thousand').values_at(:number)#=&gt; [&quot;100&quot;]</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 adds infinite? and finite? methods to Numeric]]></title>
       <author><name>Abhishek Jain</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-adds-infinite-method-to-numeric"/>
      <updated>2016-12-19T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-adds-infinite-method-to-numeric</id>
      <content type="html"><![CDATA[<h3>Prior to Ruby 2.4</h3><p>Prior to Ruby 2.4, Float and BigDecimal responded to methods <code>infinite?</code> and<code>finite?</code>, whereas Fixnum and Bignum did not.</p><h4>Ruby 2.3</h4><pre><code class="language-ruby">#infinite?5.0.infinite?=&gt; nilFloat::INFINITY.infinite?=&gt; 15.infinite?NoMethodError: undefined method `infinite?' for 5:Fixnum</code></pre><pre><code class="language-ruby">#finite?5.0.finite?=&gt; true5.finite?NoMethodError: undefined method `finite?' for 5:Fixnum</code></pre><h4>Ruby 2.4</h4><p>To make behavior for all the numeric values to be consistent,<a href="https://bugs.ruby-lang.org/issues/12039">infinite? and finite? were added to Fixnum and Bignum</a>even though they would always return nil.</p><p>This gives us ability to call these methods irrespective of whether they aresimple numbers or floating numbers.</p><pre><code class="language-ruby">#infinite?5.0.infinite?=&gt; nilFloat::INFINITY.infinite?=&gt; 15.infinite?=&gt; nil</code></pre><pre><code class="language-ruby">#finite?5.0.finite?=&gt; true5.finite?=&gt; true</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 adds Comparable#clamp method]]></title>
       <author><name>Abhishek Jain</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-adds-comparable-clamp-method"/>
      <updated>2016-12-13T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-adds-comparable-clamp-method</id>
      <content type="html"><![CDATA[<p>In Ruby 2.4,<a href="https://bugs.ruby-lang.org/issues/10594">clamp method is added to the Comparable module</a>.This method can be used to clamp an object within a specific range of values.</p><p><code>clamp</code> method takes min and max as two arguments to define the range of valuesin which the given argument should be clamped.</p><h4>Clamping numbers</h4><p><code>clamp</code> can be used to keep a number within the range of min, max.</p><pre><code class="language-ruby">10.clamp(5, 20)=&gt; 1010.clamp(15, 20)=&gt; 1510.clamp(0, 5)=&gt; 5</code></pre><h4>Clamping strings</h4><p>Similarly, strings can also be clamped within a range.</p><pre><code class="language-ruby">&quot;e&quot;.clamp(&quot;a&quot;, &quot;s&quot;)=&gt; &quot;e&quot;&quot;e&quot;.clamp(&quot;f&quot;, &quot;s&quot;)=&gt; &quot;f&quot;&quot;e&quot;.clamp(&quot;a&quot;, &quot;c&quot;)=&gt; &quot;c&quot;&quot;this&quot;.clamp(&quot;thief&quot;, &quot;thin&quot;)=&gt; &quot;thin&quot;</code></pre><p>Internally, this method relies on applying the<a href="https://en.wikipedia.org/wiki/Three-way_comparison">spaceship &lt;=&gt; operator</a>between the object and the min &amp; max arguments.</p><pre><code class="language-ruby">if x &lt;=&gt; min &lt; 0, x = min;if x &lt;=&gt; max &gt; 0 , x = maxelse x</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[New liberal_parsing option for parsing bad CSV data]]></title>
       <author><name>Ershad Kunnakkadan</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-introduces-liberal_parsing-option-for-parsing-bad-csv-data"/>
      <updated>2016-11-22T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-introduces-liberal_parsing-option-for-parsing-bad-csv-data</id>
      <content type="html"><![CDATA[<p>Comma-Separated Values (CSV) is a widely used data format and almost everylanguage has a module to parse it. In Ruby, we have<a href="http://ruby-doc.org/stdlib-2.3.2/libdoc/csv/rdoc/CSV.html">CSV class</a> to dothat.</p><p>According to <a href="https://tools.ietf.org/html/rfc4180#page-4">RFC 4180</a>, we cannothave unescaped double quotes in CSV input since such data can't be parsed.</p><p>We get <code>MalformedCSVError</code> error when the CSV data does not conform to RFC 4180.</p><p>Ruby 2.4 has added a<a href="https://bugs.ruby-lang.org/issues/11839">liberal parsing option</a> to parse suchbad data. When it is set to <code>true</code>, Ruby will try to parse the data even whenthe data does not conform to RFC 4180.</p><pre><code class="language-ruby"># Before Ruby 2.4&gt; CSV.parse_line('one,two&quot;,three,four')CSV::MalformedCSVError: Illegal quoting in line 1.# With Ruby 2.4&gt; CSV.parse_line('one,two&quot;,three,four', liberal_parsing: true)=&gt; [&quot;one&quot;, &quot;two\&quot;&quot;, &quot;three&quot;, &quot;four&quot;]</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Enumerable#chunk not mandatory in Ruby 2.4]]></title>
       <author><name>Abhishek Jain</name></author>
      <link href="https://www.bigbinary.com/blog/passing-block-with-enumerable-chunk-is-not-mandatory-in-ruby-2-4"/>
      <updated>2016-11-21T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/passing-block-with-enumerable-chunk-is-not-mandatory-in-ruby-2-4</id>
      <content type="html"><![CDATA[<p><a href="https://ruby-doc.org/core-2.3.2/Enumerable.html#method-i-chunk">Enumerable#chunk</a>method can be used on enumerator object to group consecutive items based on thevalue returned from the block passed to it.</p><pre><code class="language-ruby">[1, 4, 7, 10, 2, 6, 15].chunk { |item| item &gt; 5 }.each { |values| p values }=&gt; [false, [1, 4]][true, [7, 10]][false, [2]][true, [6, 15]]</code></pre><p>Prior to Ruby 2.4, passing a block to <code>chunk</code> method was must.</p><pre><code class="language-ruby">array = [1,2,3,4,5,6]array.chunk=&gt; ArgumentError: no block given</code></pre><h3>Enumerable#chunk without block in Ruby 2.4</h3><p>In Ruby 2.4, we will be able to use<a href="https://bugs.ruby-lang.org/issues/2172">chunk without passing block</a>. It justreturns the enumerator object which we can use to chain further operations.</p><pre><code class="language-ruby">array = [1,2,3,4,5,6]array.chunk=&gt; &lt;Enumerator: [1, 2, 3, 4, 5, 6]:chunk&gt;</code></pre><h3>Reasons for this change</h3><p>Let's take the<a href="http://stackoverflow.com/questions/8621733/how-do-i-summarize-array-of-integers-as-an-array-of-ranges">case of listing</a>consecutive integers in an array of ranges.</p><pre><code class="language-ruby"># Before Ruby 2.4integers = [1,2,4,5,6,7,9,13]integers.enum_for(:chunk).with_index { |x, idx| x - idx }.map do |diff, group|  [group.first, group.last]end=&gt; [[1,2],[4,7],[9,9],[13,13]]</code></pre><p>We had to use<a href="http://ruby-doc.org/core-2.3.2/Object.html#method-i-enum_for">enum_for</a> here as<code>chunk</code> can't be called without block.</p><p><code>enum_for</code> creates a new enumerator object which will enumerate by calling themethod passed to it. In this case the method passed was <code>chunk</code>.</p><p>With Ruby 2.4, we can use <code>chunk</code> method directly without using <code>enum_for</code> as itdoes not require a block to be passed.</p><pre><code class="language-ruby"># Ruby 2.4integers = [1,2,4,5,6,7,9,13]integers.chunk.with_index { |x, idx| x - idx }.map do |diff, group|  [group.first, group.last]end=&gt; [[1,2],[4,7],[9,9],[13,13]]</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 unifies Fixnum and Bignum into Integer]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-unifies-fixnum-and-bignum-into-integer"/>
      <updated>2016-11-18T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-unifies-fixnum-and-bignum-into-integer</id>
      <content type="html"><![CDATA[<p>Ruby uses <code>Fixnum</code> class for representing small numbers and <code>Bignum</code> class forbig numbers.</p><pre><code class="language-ruby"># Before Ruby 2.41.class         #=&gt; Fixnum(2 ** 62).class #=&gt; Bignum</code></pre><p>In general routine work we don't have to worry about whether the number we aredealing with is <code>Bignum</code> or <code>Fixnum</code>. It's just an implementation detail.</p><p>Interestingly, Ruby also has <code>Integer</code> class which is superclass for <code>Fixnum</code>and <code>Bignum</code>.</p><p>Starting with Ruby 2.4, Fixnum and Bignum<a href="https://bugs.ruby-lang.org/issues/12005">are unified into Integer</a>.</p><pre><code class="language-ruby"># Ruby 2.41.class         #=&gt; Integer(2 ** 62).class #=&gt; Integer</code></pre><p>Starting with Ruby 2.4 usage of Fixnum and Bignum constants<a href="https://bugs.ruby-lang.org/issues/12739">is deprecated</a>.</p><pre><code class="language-ruby"># Ruby 2.4&gt;&gt; Fixnum(irb):6: warning: constant ::Fixnum is deprecated=&gt; Integer&gt;&gt; Bignum(irb):7: warning: constant ::Bignum is deprecated=&gt; Integer</code></pre><h2>How to know if a number is Fixnum, Bignum or Integer?</h2><p>We don't have to worry about this change most of the times in our applicationcode. But libraries like Rails use the class of numbers for taking certaindecisions. These libraries need to support both Ruby 2.4 and previous versionsof Ruby.</p><p>Easiest way to know whether the Ruby version is using integer unification or notis to check class of 1.</p><pre><code class="language-ruby"># Ruby 2.41.class #=&gt; Integer# Before Ruby 2.41.class #=&gt; Fixnum</code></pre><p>Look at <a href="https://github.com/rails/rails/pull/25056">PR #25056</a> to see how Railsis handling this case.</p><p>Similarly Arel is<a href="https://github.com/rails/arel/commit/dc85a6e9c74942945ad696f5da4d82490a85b865">also supporting</a>both Ruby 2.4 and previous versions of Ruby.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 implements Array#min and Array#max]]></title>
       <author><name>Rohit Kumar</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-implements-array-min-and-max"/>
      <updated>2016-11-17T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-implements-array-min-and-max</id>
      <content type="html"><![CDATA[<p>Ruby has <code>Enumerable#min</code> and <code>Enumerable#max</code> which can be used to find theminimum and the maximum value in an Array.</p><pre><code class="language-ruby">(1..10).to_a.max#=&gt; 10(1..10).to_a.method(:max)#=&gt; #&lt;Method: Array(Enumerable)#max&gt;</code></pre><p>Ruby 2.4 adds <a href="https://bugs.ruby-lang.org/issues/12172">Array#min and Array#max</a>which are much faster than <code>Enumerable#max</code> and <code>Enuermable#min</code>.</p><p>Following benchmark is based on<a href="https://blog.blockscore.com/new-features-in-ruby-2-4">https://blog.blockscore.com/new-features-in-ruby-2-4</a>.</p><pre><code class="language-ruby">Benchmark.ips do |bench|  NUM1 = 1_000_000.times.map { rand }  NUM2 = NUM1.dup  ENUM_MAX = Enumerable.instance_method(:max).bind(NUM1)  ARRAY_MAX = Array.instance_method(:max).bind(NUM2)  bench.report('Enumerable#max') do    ENUM_MAX.call  end  bench.report('Array#max') do    ARRAY_MAX.call  end  bench.compare!endWarming up --------------------------------------      Enumerable#max     1.000  i/100ms           Array#max     2.000  i/100msCalculating -------------------------------------      Enumerable#max     17.569  ( 5.7%) i/s -     88.000  in   5.026996s           Array#max     26.703  ( 3.7%) i/s -    134.000  in   5.032562sComparison:           Array#max:       26.7 i/s      Enumerable#max:       17.6 i/s - 1.52x  slowerBenchmark.ips do |bench|  NUM1 = 1_000_000.times.map { rand }  NUM2 = NUM1.dup  ENUM_MIN = Enumerable.instance_method(:min).bind(NUM1)  ARRAY_MIN = Array.instance_method(:min).bind(NUM2)  bench.report('Enumerable#min') do    ENUM_MIN.call  end  bench.report('Array#min') do    ARRAY_MIN.call  end  bench.compare!endWarming up --------------------------------------      Enumerable#min     1.000  i/100ms           Array#min     2.000  i/100msCalculating -------------------------------------      Enumerable#min     18.621  ( 5.4%) i/s -     93.000  in   5.007244s           Array#min     26.902  ( 3.7%) i/s -    136.000  in   5.064815sComparison:           Array#min:       26.9 i/s      Enumerable#min:       18.6 i/s - 1.44x  slower</code></pre><p>This benchmark shows that the new methods <code>Array#max</code> and <code>Array#min</code> are about1.5 times faster than <code>Enumerable#max</code> and <code>Enumerable#min</code>.</p><p>Similar to <code>Enumerable#max</code> and <code>Enumerable#min</code>, <code>Array#max</code> and <code>Array#min</code>also assumes that the objects use<a href="https://ruby-doc.org/core-2.3.2/Comparable.html">Comparable</a> mixin to define<code>spaceship &lt;=&gt;</code> operator for comparing the elements.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 Extracting captured data from Regexp results]]></title>
       <author><name>Rohit Kumar</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-adds-better-support-for-extracting-captured-data-from-regexp-match-results"/>
      <updated>2016-11-10T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-adds-better-support-for-extracting-captured-data-from-regexp-match-results</id>
      <content type="html"><![CDATA[<p>Ruby has <a href="https://ruby-doc.org/core-2.2.0/MatchData.html">MatchData</a> type whichis returned by <code>Regexp#match</code> and <code>Regexp.last_match</code>.</p><p>It has methods <code>#names</code> and <code>#captures</code> to return the names used for capturingand the actual captured data respectively.</p><pre><code class="language-ruby">pattern = /(?&lt;number&gt;\d+) (?&lt;word&gt;\w+)/match_data = pattern.match('100 thousand')#=&gt; #&lt;MatchData &quot;100 thousand&quot; number:&quot;100&quot; word:&quot;thousand&quot;&gt;&gt;&gt; match_data.names=&gt; [&quot;number&quot;, &quot;word&quot;]&gt;&gt; match_data.captures=&gt; [&quot;100&quot;, &quot;thousand&quot;]</code></pre><p>If we want all named captures in a key value pair, we have to combine the resultof names and captures.</p><pre><code class="language-ruby">match_data.names.zip(match_data.captures).to_h#=&gt; {&quot;number&quot;=&gt;&quot;100&quot;, &quot;word&quot;=&gt;&quot;thousand&quot;}</code></pre><p>Ruby 2.4 adds <a href="https://bugs.ruby-lang.org/issues/11999"><code>#named_captures</code></a> whichreturns both the name and data of the capture groups.</p><pre><code class="language-ruby">pattern=/(?&lt;number&gt;\d+) (?&lt;word&gt;\w+)/match_data = pattern.match('100 thousand')match_data.named_captures#=&gt; {&quot;number&quot;=&gt;&quot;100&quot;, &quot;word&quot;=&gt;&quot;thousand&quot;}</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 Regexp#match? not polluting global variables]]></title>
       <author><name>Rohit Kumar</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-implements-regexp-match-without-polluting-global-variables"/>
      <updated>2016-11-04T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-implements-regexp-match-without-polluting-global-variables</id>
      <content type="html"><![CDATA[<p>Ruby has many ways to match with a regular expression.</p><h4>Regexp#===</h4><p>It returns true/false and sets the $~ global variable.</p><pre><code class="language-ruby">/stat/ === &quot;case statements&quot;#=&gt; true$~#=&gt; #&lt;MatchData &quot;stat&quot;&gt;</code></pre><h3>Regexp#=~</h3><p>It returns integer position it matched or nil if no match. It also sets the $~global variable.</p><pre><code class="language-ruby">/stat/ =~ &quot;case statements&quot;#=&gt; 5$~#=&gt; #&lt;MatchData &quot;stat&quot;&gt;</code></pre><h3>Regexp#match</h3><p>It returns match data and also sets the $~ global variable.</p><pre><code class="language-ruby">/stat/.match(&quot;case statements&quot;)#=&gt; #&lt;MatchData &quot;stat&quot;&gt;$~#=&gt; #&lt;MatchData &quot;stat&quot;&gt;</code></pre><h3>Ruby 2.4 adds Regexp#match?</h3><p><a href="https://bugs.ruby-lang.org/issues/8110">This new method</a> just returnstrue/false and does not set any global variables.</p><pre><code class="language-ruby">/case/.match?(&quot;case statements&quot;)#=&gt; true</code></pre><p>So <code>Regexp#match?</code> is good option when we are only concerned with the fact thatregex matches or not.</p><p><code>Regexp#match?</code> is also faster than its counterparts as it reduces objectallocation by not creating a back reference and changing <code>$~</code>.</p><pre><code class="language-ruby">require 'benchmark/ips'Benchmark.ips do |bench|  EMAIL_ADDR = 'disposable.style.email.with+symbol@example.com'  EMAIL_REGEXP_DEVISE = /\A[^@\s]+@([^@\s]+\.)+[^@\W]+\z/  bench.report('Regexp#===') do    EMAIL_REGEXP_DEVISE === EMAIL_ADDR  end  bench.report('Regexp#=~') do    EMAIL_REGEXP_DEVISE =~ EMAIL_ADDR  end  bench.report('Regexp#match') do    EMAIL_REGEXP_DEVISE.match(EMAIL_ADDR)  end  bench.report('Regexp#match?') do    EMAIL_REGEXP_DEVISE.match?(EMAIL_ADDR)  end  bench.compare!end#=&gt; Warming up --------------------------------------#=&gt;          Regexp#===   103.876k i/100ms#=&gt;           Regexp#=~   105.843k i/100ms#=&gt;        Regexp#match    58.980k i/100ms#=&gt;       Regexp#match?   107.287k i/100ms#=&gt; Calculating -------------------------------------#=&gt;          Regexp#===      1.335M ( 9.5%) i/s -      6.648M in   5.038568s#=&gt;           Regexp#=~      1.369M ( 6.7%) i/s -      6.880M in   5.049481s#=&gt;        Regexp#match    709.152k ( 5.4%) i/s -      3.539M in   5.005514s#=&gt;       Regexp#match?      1.543M ( 4.6%) i/s -      7.725M in   5.018696s#=&gt;#=&gt; Comparison:#=&gt;       Regexp#match?:  1542589.9 i/s#=&gt;           Regexp#=~:  1369421.3 i/s - 1.13x  slower#=&gt;          Regexp#===:  1335450.3 i/s - 1.16x  slower#=&gt;        Regexp#match:   709151.7 i/s - 2.18x  slower</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.4 implements Enumerable#sum]]></title>
       <author><name>Mohit Natoo</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-4-introduces-enumerable-sum"/>
      <updated>2016-11-02T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-4-introduces-enumerable-sum</id>
      <content type="html"><![CDATA[<p>It is a common use case to calculate sum of the elements of an array or valuesfrom a hash.</p><pre><code class="language-ruby">[1, 2, 3, 4] =&gt; 10{a: 1, b: 6, c: -3} =&gt; 4</code></pre><p>Active Support already implements<a href="https://github.com/rails/rails/blob/3d716b9e66e334c113c98fb3fc4bcf8a945b93a1/activesupport/lib/active_support/core_ext/enumerable.rb#L2-L27">Enumerable#sum</a></p><pre><code class="language-ruby">&gt; [1, 2, 3, 4].sum #=&gt; 10&gt; {a: 1, b: 6, c: -3}.sum{ |k, v| v**2 } #=&gt; 46&gt; ['foo', 'bar'].sum # concatenation of strings #=&gt; &quot;foobar&quot;&gt; [[1], ['abc'], [6, 'qwe']].sum # concatenation of arrays #=&gt; [1, &quot;abc&quot;, 6, &quot;qwe&quot;]</code></pre><p>Until Ruby 2.3, we had to use Active Support to use <code>Enumerable#sum</code> method orwe could use <code>#inject</code> which is<a href="https://github.com/rails/rails/blob/3d716b9e66e334c113c98fb3fc4bcf8a945b93a1/activesupport/lib/active_support/core_ext/enumerable.rb#L2-L27">used by Active Support under the hood</a>.</p><p>Ruby 2.4.0 implements<a href="https://github.com/ruby/ruby/commit/41ef7ec381338a97d15a6b4b18acd8b426a9ce79">Enumerable#sum</a>as <a href="https://bugs.ruby-lang.org/issues/12217">part of the language</a> itself.</p><p>Let's take a look at how <code>sum</code> method fares on some of the enumerable objects inRuby 2.4.</p><pre><code class="language-ruby">&gt; [1, 2, 3, 4].sum #=&gt; 10&gt; {a: 1, b: 6, c: -3}.sum { |k, v| v**2 } #=&gt; 46&gt; ['foo', 'bar'].sum #=&gt; TypeError: String can't be coerced into Integer&gt; [[1], ['abc'], [6, 'qwe']].sum #=&gt; TypeError: Array can't be coerced into Integer</code></pre><p>As we can see, the behavior of <code>Enumerable#sum</code> from Ruby 2.4 is same as that ofActive Support in case of numbers but not the same in case of string or arrayconcatenation. Let's see what is the difference and how we can make it work inRuby 2.4 as well.</p><h3>Understanding addition/concatenation identity</h3><p>The <code>Enumerable#sum</code> method takes an optional argument which acts as anaccumulator. Both Active Support and Ruby 2.4 accept this argument.</p><p>When identity argument is not passed, <code>0</code> is used as default accumulator in Ruby2.4 whereas Active Support uses <code>nil</code> as default accumulator.</p><p>Hence in the cases of string and array concatenation, the error occurred in Rubybecause the code attempts to add a string and array respectively to <code>0</code>.</p><p>To overcome this, we need to pass proper addition/concatenation identity as anargument to the <code>sum</code> method.</p><p>The addition/concatenation identity of an object can be defined as the valuewith which calling <code>+</code> operation on an object returns the same object.</p><pre><code class="language-ruby">&gt; ['foo', 'bar'].sum('') #=&gt; &quot;foobar&quot;&gt; [[1], ['abc'], [6, 'qwe']].sum([]) #=&gt; [1, &quot;abc&quot;, 6, &quot;qwe&quot;]</code></pre><h3>What about Rails ?</h3><p>As we have seen earlier, Ruby 2.4 implements <code>Enumerable#sum</code> favouring numericoperations whereas also supporting non-numeric callers with the identityelement. This behavior is not entirely same as that of Active Support. But stillActive Support can make use of the native sum method whenever possible. There isalready a <a href="https://github.com/rails/rails/pull/25202">pull request</a> open whichuses <code>Enumerable#sum</code> from Ruby whenever possible. This will help gain someperformance boost as the Ruby's method is implemented natively in C whereas thatin Active Support is implemented in Ruby.</p>]]></content>
    </entry><entry>
       <title><![CDATA[String#concat, Array#concat & String#prepend Ruby 2.4]]></title>
       <author><name>Abhishek Jain</name></author>
      <link href="https://www.bigbinary.com/blog/string-array-concat-and-string-prepend-take-multiple-arguments-in-ruby-2-4"/>
      <updated>2016-10-28T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/string-array-concat-and-string-prepend-take-multiple-arguments-in-ruby-2-4</id>
      <content type="html"><![CDATA[<p>In Ruby, we use <code>#concat</code> to append a string to another string or an element tothe array. We can also use <code>#prepend</code> to add a string at the beginning of astring.</p><h3>Ruby 2.3</h3><h4>String#concat and Array#concat</h4><pre><code class="language-ruby">string = &quot;Good&quot;string.concat(&quot; morning&quot;)#=&gt; &quot;Good morning&quot;array = ['a', 'b', 'c']array.concat(['d'])#=&gt; [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;]</code></pre><h4>String#prepend</h4><pre><code class="language-ruby">string = &quot;Morning&quot;string.prepend(&quot;Good &quot;)#=&gt; &quot;Good morning&quot;</code></pre><p>Before Ruby 2.4, we could pass only one argument to these methods. So we couldnot add multiple items in one shot.</p><pre><code class="language-ruby">string = &quot;Good&quot;string.concat(&quot; morning&quot;, &quot; to&quot;, &quot; you&quot;)#=&gt; ArgumentError: wrong number of arguments (given 3, expected 1)</code></pre><h3>Changes with Ruby 2.4</h3><p>In Ruby 2.4, we can pass multiple arguments and Ruby processes each argument oneby one.</p><h4>String#concat and Array#concat</h4><pre><code class="language-ruby">string = &quot;Good&quot;string.concat(&quot; morning&quot;, &quot; to&quot;, &quot; you&quot;)#=&gt; &quot;Good morning to you&quot;array = ['a', 'b']array.concat(['c'], ['d'])#=&gt; [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;]</code></pre><h4>String#prepend</h4><pre><code class="language-ruby">string = &quot;you&quot;string.prepend(&quot;Good &quot;, &quot;morning &quot;, &quot;to &quot;)#=&gt; &quot;Good morning to you&quot;</code></pre><p>These methods work even when no argument is passed unlike in previous versionsof Ruby.</p><pre><code class="language-ruby">&quot;Good&quot;.concat#=&gt; &quot;Good&quot;</code></pre><h4>Difference between <code>concat</code> and shovel <code>&lt;&lt;</code> operator</h4><p>Though shovel <code>&lt;&lt;</code> operator can be used interchangeably with <code>concat</code> when weare calling it once, there is a difference in the behavior when calling itmultiple times.</p><pre><code class="language-ruby">str = &quot;Ruby&quot;str &lt;&lt; strstr#=&gt; &quot;RubyRuby&quot;str = &quot;Ruby&quot;str.concat strstr#=&gt; &quot;RubyRuby&quot;str = &quot;Ruby&quot;str &lt;&lt; str &lt;&lt; str#=&gt; &quot;RubyRubyRubyRuby&quot;str = &quot;Ruby&quot;str.concat str, strstr#=&gt; &quot;RubyRubyRuby&quot;</code></pre><p>So <code>concat</code> behaves as appending <code>present</code> content to the caller twice. Whereascalling <code>&lt;&lt;</code> twice is just sequence of binary operations. So the argument forthe second call is output of the first <code>&lt;&lt;</code> operation.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Hash#compact and Hash#compact! now part of Ruby 2.4]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/hash-compact-and-hash-compact-now-part-of-ruby-2-4"/>
      <updated>2016-10-24T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/hash-compact-and-hash-compact-now-part-of-ruby-2-4</id>
      <content type="html"><![CDATA[<p>It is a common use case to remove the <code>nil</code> values from a hash in Ruby.</p><pre><code class="language-ruby">{ &quot;name&quot; =&gt; &quot;prathamesh&quot;, &quot;email&quot; =&gt; nil} =&gt; { &quot;name&quot; =&gt; &quot;prathamesh&quot; }</code></pre><p>Active Support already has a solution for this in the form of<a href="http://api.rubyonrails.org/classes/Hash.html#method-i-compact">Hash#compact</a>and<a href="http://api.rubyonrails.org/classes/Hash.html#method-i-compact-21">Hash#compact!</a>.</p><pre><code class="language-ruby">hash = { &quot;name&quot; =&gt; &quot;prathamesh&quot;, &quot;email&quot; =&gt; nil}hash.compact #=&gt; { &quot;name&quot; =&gt; &quot;prathamesh&quot; }hash #=&gt; { &quot;name&quot; =&gt; &quot;prathamesh&quot;, &quot;email&quot; =&gt; nil}hash.compact! #=&gt; { &quot;name&quot; =&gt; &quot;prathamesh&quot; }hash #=&gt; { &quot;name&quot; =&gt; &quot;prathamesh&quot; }</code></pre><p>Now, Ruby 2.4 will have these 2 methods in the<a href="https://bugs.ruby-lang.org/issues/11818">language</a><a href="https://bugs.ruby-lang.org/issues/12863">itself</a>, so even those not using Railsor Active Support will be able to use them. Additionally it will also giveperformance boost over the Active Support versions because now these methods areimplemented in C natively whereas the Active Support versions are in Ruby.</p><p>There is already a<a href="https://github.com/rails/rails/pull/26868">pull request open</a> in Rails to usethe native versions of these methods from Ruby 2.4 whenever available so that wewill be able to use the performance boost.</p>]]></content>
    </entry>
     </feed>