<?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-03-08T07:48:09+00:00</updated>
     <id>https://www.bigbinary.com/</id>
     <entry>
       <title><![CDATA[MJIT Support in Ruby 2.6]]></title>
       <author><name>Sudeep Tarlekar</name></author>
      <link href="https://www.bigbinary.com/blog/mjit-support-in-ruby-2-6"/>
      <updated>2019-03-05T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/mjit-support-in-ruby-2-6</id>
      <content type="html"><![CDATA[<h3>What is JIT?</h3><p>JIT stands for Just-In-Time compiler. JIT converts repetitive code into bytecodewhich can then be sent to the processor directly, hence, saving time by notcompiling the same piece of code over and over.</p><h3>Ruby 2.6</h3><p>MJIT is introduced in Ruby 2.6. It is most commonly known as MRI JIT or MethodBased JIT.</p><p>It is a part of the Ruby 3x3 project started by Matz. The name &quot;Ruby 3x3&quot;signifies Ruby 3.0 will be 3 times faster than Ruby 2.0 and it will focus mainlyon performance. In addition to performance, it also aims for the followingthings:</p><ol><li>Portability</li><li>Stability</li><li>Security</li></ol><p>MJIT is still in development, therefore, MJIT is optional in Ruby 2.6. If youare running Ruby 2.6, then you can execute the following command.</p><pre><code class="language-shell">ruby --help</code></pre><p>You will see following options.</p><pre><code class="language-shell">--Jit-wait # Wait program execution until code compiles.--jit-verbose=num # Level information MJIT compiler prints for Ruby program.--jit-min-calls=num # Minimum count in loops for which MJIT should work.--jit-max-cache--jit-save-temps # Save compiled library to the file.</code></pre><p>Vladimir Makarov proposed improving performance by replacing VM instructionswith RTL(Register Transfer Language) and introducing the Method based JITcompiler.</p><p>Vladimir explained MJIT architecture in his<a href="https://youtu.be/qpZDw-p9yag?t=1655">RubyKaigi 2017 conference keynote</a>.</p><p>Ruby's compiler converts the code to YARV(Yet Another Ruby VM) instructions andthen these instructions are run by the Ruby Virtual Machine. Code that isexecuted too often is converted to RTL instructions, which runs faster.</p><p>Let's take a look at how MJIT works.</p><pre><code class="language-ruby"># mjit.rbrequire 'benchmark'puts Benchmark.measure {def test_whilestart_time = Time.nowi = 0    while i &lt; 4      i += 1    end    i    puts Time.now - start_timeend4.times { test_while }}</code></pre><p>Let's run this code with MJIT options and check what we got.</p><pre><code class="language-shell">ruby --jit --jit-verbose=1 --jit-wait --disable-gems mjit.rb</code></pre><pre><code class="language-shell">Time taken is 4.0e-06Time taken is 0.0Time taken is 0.0Time taken is 0.00.000082 0.000032 0.000114 ( 0.000105)Successful MJIT finish</code></pre><p>Nothing interesting right? And why is that? because we are iterating the loopfor 4 times and default value for MJIT to work is 5. We can always decide afterhow many calls MJIT should work by providing <code>--jit-min-calls=#number</code> option.</p><p>Let's tweak the program a bit so MJIT gets to work.</p><pre><code class="language-ruby">require 'benchmark'puts Benchmark.measure {def test_whilestart_time = Time.nowi = 0    while i &lt; 4_00_00_000      i += 1    end    puts &quot;Time taken is #{Time.now - start_time}&quot;end10.times { test_while }}</code></pre><p>After running the above code we can see some work done by MJIT.</p><pre><code class="language-shell">Time taken is 0.457916Time taken is 0.455921Time taken is 0.454672Time taken is 0.452823JIT success (72.5ms): block (2 levels) in &lt;main&gt;@mjit.rb:15 -&gt; /var/folders/v6/\_6sh53vn5gl3lct18w533gr80000gn/T//\_ruby_mjit_p66220u0.cJIT success (140.9ms): test_while@mjit.rb:4 -&gt; /var/folders/v6/\_6sh53vn5gl3lct18w533gr80000gn/T//\_ruby_mjit_p66220u1.cJIT compaction (23.0ms): Compacted 2 methods -&gt; /var/folders/v6/\_6sh53vn5gl3lct18w533gr80000gn/T//\_ruby_mjit_p66220u2.bundleTime taken is 0.463703Time taken is 0.102852Time taken is 0.103335Time taken is 0.103299Time taken is 0.103252Time taken is 0.1032612.797843 0.005357 3.141944 ( 2.801391)Successful MJIT finish</code></pre><p>Here's what's happening. Method ran 4 times and on the 5th call it found it isrunning same code again. So MJIT started a separate thread to convert the codeinto RTL instructions, which created a shared object library. Next, threads tookthat shared code and executed directly. As we passed option <code>--jit-verbose=1</code> wecan see what MJIT did.</p><p>What we are seeing in output is the following:</p><ol><li>Time taken to compile.</li><li>What block of code is compiled by JIT.</li><li>Location of compiled code.</li></ol><p>We can open the file and see how MJIT converted the piece of code to binaryinstructions but for that we need to pass another option which is<code>--jit-save-temps</code> and then just inspect those files.</p><p>After compiling the code to RTL instructions, take a look at the execution time.It dropped down to 0.10 ms from 0.46 ms. That's a neat speed bump.</p><p>Here is a comparison across some of the Ruby versions for some basic operations.</p><p>![Ruby time comparison in different versions](/blog_images/imageruby_mjit_execution_comparison.png)</p><h2>Rails comparison on Ruby 2.5, Ruby 2.6 and Ruby 2.6 with JIT</h2><p>Create a rails application with different Ruby versions and start a server. Wecan start the rails server with the JIT option, as shown below.</p><pre><code class="language-shell">RUBYOPT=&quot;--jit&quot; bundle exec rails s</code></pre><p>Now, we can start testing the performance on servers. We found that Ruby 2.6 isfaster than Ruby 2.5, but enabling JIT in Ruby 2.6 does not add more value tothe Rails application.</p><h2>MJIT status and future directions</h2><ul><li>It is in an early development stage.</li><li>Does not work on windows.</li><li>Needs more time to mature.</li><li>Needs more optimisations.</li><li>MJIT can use GCC or LLVM in the future C Compilers.</li></ul><h2>Further reading</h2><ol><li><a href="https://developers.redhat.com/blog/2018/03/22/ruby-3x3-performance-goal">Ruby 3x3 Performance Goal</a></li><li><a href="https://medium.com/@k0kubun/the-method-jit-compiler-for-ruby-2-6-388ee0989c13">The method JIT compiler for Ruby2.6</a></li><li><a href="https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch">Vladimir Makarov's Ruby Edition</a></li></ol>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 Range#cover? accepts Range object as argument]]></title>
       <author><name>Abhay Nikam</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-range-cover-now-accepts-range-object"/>
      <updated>2018-10-24T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-range-cover-now-accepts-range-object</id>
      <content type="html"><![CDATA[<p><code>Range#cover?</code> returns true if the object passed as argument is in the range.</p><pre><code class="language-ruby">(1..10).cover?(5)=&gt; true</code></pre><p><code>Range#cover?</code> returns false if the object passed as an argument isnon-comparable or is not in the range.</p><p>Before Ruby 2.6, <code>Range#cover?</code> used to return false if a Range object is passedas an argument.</p><pre><code class="language-ruby">&gt;&gt; (1..10).cover?(2..5)=&gt; false</code></pre><h4>Ruby 2.6</h4><p>In Ruby 2.6 <code>Range#cover?</code> can accept a Range object as an argument. It returnstrue if the argument Range is equal to or a subset of the Range.</p><pre><code class="language-ruby">(1..100).cover?(10..20)=&gt; true(1..10).cover?(2..5)=&gt; true(5..).cover?(4..)=&gt; false(&quot;a&quot;..&quot;d&quot;).cover?(&quot;x&quot;..&quot;z&quot;)=&gt; false</code></pre><p>Here is relevant<a href="https://github.com/ruby/ruby/commit/9ca738927293df1c7a2a1ed7e2d6cf89527b5438">commit</a>and <a href="https://bugs.ruby-lang.org/issues/14473">discussion</a> for this change.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds RubyVM::AST module]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-adds-rubyvm-ast-module"/>
      <updated>2018-10-02T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-adds-rubyvm-ast-module</id>
      <content type="html"><![CDATA[<p>Ruby 2.6 added <code>RubyVM::AST</code> to generate the<a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree">Abstract Syntax Tree</a> ofcode. Please note, this feature is experimental and under active development.</p><p>As of now, <code>RubyVM::AST</code> supports two methods: <code>parse</code> and <code>parse_file</code>.</p><p><code>parse</code> method takes a string as a parameter and returns the root node of thetree in the form of the object, RubyVM::AST::Node (Link is not available).</p><p><code>parse_file</code> method takes the file name as a parameter and returns the root nodeof the tree in the form of the object,<a href="https://ruby-doc.org/core-2.6.0.preview2/RubyVM/AST/Node.html">RubyVM::AST::Node</a>.</p><h4>Ruby 2.6.0-preview2</h4><pre><code class="language-ruby">irb&gt; RubyVM::AST.parse(&quot;(1..100).select { |num| num % 5 == 0 }&quot;)=&gt; #&lt;RubyVM::AST::Node(NODE_SCOPE(0) 1:0, 1:38): &gt;irb&gt; RubyVM::AST.parse_file(&quot;/Users/amit/app.rb&quot;)=&gt; #&lt;RubyVM::AST::Node(NODE_SCOPE(0) 1:0, 1:38): &gt;</code></pre><p><a href="https://ruby-doc.org/core-2.6.0.preview2/RubyVM/AST/Node.html">RubyVM::AST::Node</a>has seven public instance methods - <code>children</code>, <code>first_column</code>, <code>first_lineno</code>,<code>inspect</code>, <code>last_column</code>, <code>last_lineno</code> and <code>type</code>.</p><h4>Ruby 2.6.0-preview2</h4><pre><code class="language-ruby">irb&gt; ast_node = RubyVM::AST.parse(&quot;(1..100).select { |num| num % 5 == 0 }&quot;)=&gt; #&lt;RubyVM::AST::Node(NODE_SCOPE(0) 1:0, 1:38): &gt;irb&gt; ast_node.children=&gt; [nil, #&lt;RubyVM::AST::Node(NODE_ITER(9) 1:0, 1:38): &gt;]irb&gt; ast_node.first_column=&gt; 0irb&gt; ast_node.first_lineno=&gt; 1irb&gt; ast_node.inspect=&gt; &quot;#&lt;RubyVM::AST::Node(NODE_SCOPE(0) 1:0, 1:38): &gt;&quot;irb&gt; ast_node.last_column=&gt; 38irb&gt; ast_node.last_lineno=&gt; 1irb&gt; ast_node.type=&gt; &quot;NODE_SCOPE&quot;</code></pre><p>This module will majorly help in building a static code analyzer and formatter.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds Enumerable#filter as alias of Enumerable#select]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-adds-enumerable-filter-as-an-alias-of-enumerable-select"/>
      <updated>2018-08-28T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-adds-enumerable-filter-as-an-alias-of-enumerable-select</id>
      <content type="html"><![CDATA[<p>Ruby 2.6 has added <code>Enumerable#filter</code> as an alias of <code>Enumerable#select</code>. Thereason for adding <code>Enumerable#filter</code> as an alias is to make it easier forpeople coming from other languages to use Ruby. A lot of other languages,including Java, R, PHP etc., have a filter method to filter/select records basedon a condition.</p><p>Let's take an example in which we have to select/filter all numbers which aredivisible by 5 from a range.</p><h4>Ruby 2.5</h4><pre><code class="language-ruby">irb&gt; (1..100).select { |num| num % 5 == 0 }=&gt; [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]irb&gt; (1..100).filter { |num| num % 5 == 0 }=&gt; Traceback (most recent call last):2: from /Users/amit/.rvm/rubies/ruby-2.5.1/bin/irb:11:in `&lt;main&gt;' 1: from (irb):2 NoMethodError (undefined method`filter' for 1..100:Range)</code></pre><h4>Ruby 2.6.0-preview2</h4><pre><code class="language-ruby">irb&gt; (1..100).select { |num| num % 5 == 0 }=&gt; [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]irb&gt; (1..100).filter { |num| num % 5 == 0 }=&gt; [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]</code></pre><p>Also note, along with <code>Enumerable#filter</code>, <code>Enumerable#filter!</code>,<code>Enumerable#select!</code> was also added as an alias.</p><p>Here is the relevant <a href="https://github.com/ruby/ruby/commit/b1a8c64483">commit</a>and <a href="https://bugs.ruby-lang.org/issues/13784">discussion</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds support for non-ASCII capital letter]]></title>
       <author><name>Rohan Pujari</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2.6-adds-support-for-non-ascii-capital-case-constant"/>
      <updated>2018-08-22T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2.6-adds-support-for-non-ascii-capital-case-constant</id>
      <content type="html"><![CDATA[<p>Before Ruby 2.6, constant must have a capital ASCII letter as the firstcharacter. It means class and module name cannot start with non-ASCII capitalcharacter.</p><p>Below code will raise <code>class/module name must be CONSTANT</code> exception.</p><pre><code class="language-ruby">  class   end</code></pre><p>We can use above non-ASCII character as a method name or variable name though.</p><p>Below code will run without any exception</p><pre><code class="language-ruby">  class NonAsciiMethodAndVariable    def        = &quot;BigBinary&quot;    end  end</code></pre><p>&quot;&quot; is treated as a variable name in above example, even though firstletter() is a capital non-ASCII character.</p><h4>Ruby 2.6</h4><p>Ruby 2.6 relaxes above mentioned limitation. We can now define constants inlanguages other than English. Languages having capital letters like Russian andGreek can be used to define constant name.</p><p>Below code will run without exception in any Ruby 2.6.</p><pre><code class="language-ruby">  class   end</code></pre><p>As capital non-Ascii characters are now treated as constant, below code willraise a warning in Ruby 2.6.</p><pre><code class="language-ruby">  irb(main):001:0&gt;  = &quot;BigBinary&quot;  =&gt; &quot;BigBinary&quot;  irb(main):002:0&gt;  = &quot;BigBinary&quot;  (irb):2: warning: already initialized constant   (irb):1: warning: previous definition of  was here</code></pre><p>Above code will run without any warnings on Ruby versions prior to 2.6</p><p>Here is relevant <a href="https://github.com/ruby/ruby/commit/f852af">commit</a> and<a href="https://bugs.ruby-lang.org/issues/13770">discussion</a> for this change.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds write_timeout to Net::HTTP]]></title>
       <author><name>Taha Husain</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-adds-write-timeout-to-net-http"/>
      <updated>2018-08-14T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-adds-write-timeout-to-net-http</id>
      <content type="html"><![CDATA[<p>Before Ruby 2.6, if we created a large request with <code>Net::HTTP</code>, it would hangforever until request is interrupted. To fix this issue,<a href="https://docs.ruby-lang.org/en/trunk/Net/HTTP.html#attribute-i-write_timeout">write_timeout</a>attribute and<a href="https://docs.ruby-lang.org/en/trunk/Net/HTTP.html#method-i-write_timeout-3D">write_timeout=</a>method is added to <a href="https://docs.ruby-lang.org/en/2.6.0/">Net::HTTP</a> in Ruby2.6. Default value for <code>write_timeout</code> is 60 seconds and can be set to aninteger or a float value.</p><p>Similarly, <code>write_timeout</code> attribute and <code>write_timeout=</code> method is added to<code>Net::BufferedIO</code> class.</p><p>If any chunk of response is not written within number of seconds provided to<code>write_timeout</code>, <a href="https://docs.ruby-lang.org/en/2.6.0/">Net::WriteTimeout</a>exception is raised. <code>Net::WriteTimeout</code> exception is not raised on Windowssystems.</p><h6>Example</h6><pre><code class="language-ruby"># server.rbrequire 'socket'server = TCPServer.new('localhost', 2345)loop dosocket = server.acceptend</code></pre><h5>Ruby 2.5.1</h5><pre><code class="language-ruby"># client.rbrequire 'net/http'connection = Net::HTTP.new('localhost', 2345)connection.open_timeout = 1connection.read_timeout = 3connection.startpost = Net::HTTP::Post.new('/')body = (('a' _ 1023) + &quot;\n&quot;) _ 5_000post.body = bodyputs &quot;Sending #{body.bytesize} bytes&quot;connection.request(post)</code></pre><h6>Output</h6><pre><code class="language-ruby">\$ RBENV_VERSION=2.5.1 ruby client.rbSending 5120000 bytes</code></pre><p>Ruby 2.5.1 processes request endlessly unless above program is interrupted.</p><h5>Ruby 2.6.0-dev</h5><p>Add <code>write_timeout</code> attribute to <code>Net::HTTP</code> instance in client.rb program.</p><pre><code class="language-ruby"># client.rbrequire 'net/http'connection = Net::HTTP.new('localhost', 2345)connection.open_timeout = 1connection.read_timeout = 3# set write_timeout to 10 secondsconnection.write_timeout = 10connection.startpost = Net::HTTP::Post.new('/')body = (('a' _ 1023) + &quot;\n&quot;) _ 5_000post.body = bodyputs &quot;Sending #{body.bytesize} bytes&quot;connection.request(post)</code></pre><h6>Output</h6><pre><code class="language-ruby">\$ RBENV_VERSION=2.6.0-dev ruby client.rbSending 5120000 bytesTraceback (most recent call last):13: `from client.rb:17:in `&lt;main&gt;`` 12: `from /net/http.rb:1479:in `request``11: `from /net/http.rb:1506:in `transport_request`` 10: `from /net/http.rb:1506:in `catch``9: `from /net/http.rb:1507:in `block in transport_request`` 8: `from /net/http/generic_request.rb:123:in `exec``7: `from /net/http/generic_request.rb:189:in `send_request_with_body`` 6: `from /net/protocol.rb:221:in `write``5: `from /net/protocol.rb:239:in `writing`` 4: `from /net/protocol.rb:222:in `block in write``3: `from /net/protocol.rb:249:in `write0`` 2: `from /net/protocol.rb:249:in `each_with_index``1: `from /net/protocol.rb:249:in `each`` `/net/protocol.rb:270:in `block in write0`: Net::WriteTimeout (Net::WriteTimeout)`</code></pre><p>In Ruby 2.6.0, above program is terminated raising <code>Net::WriteTimeout</code> exceptionafter 10 seconds (value set to <code>write_timeout</code> attribute).</p><p>Here is relevant <a href="https://github.com/ruby/ruby/commit/bd7c46">commit</a> and<a href="https://bugs.ruby-lang.org/issues/13396">discussion</a> for this change.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds Dir#each_child & Dir#children instance]]></title>
       <author><name>Tejaswini Chile</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-introduces-dir-each_child-and-dir-children-instance-methods"/>
      <updated>2018-08-07T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-introduces-dir-each_child-and-dir-children-instance-methods</id>
      <content type="html"><![CDATA[<p>Ruby 2.5 had introduced class level methods<a href="https://ruby-doc.org/core-2.5.1/Dir.html#method-c-each_child">Dir::each_child</a>and <a href="https://ruby-doc.org/core-2.5.1/Dir.html#method-c-children">Dir::children</a>.We wrote a<a href="https://blog.bigbinary.com/2017/11/21/ruby-2_5-introduces-dir-children-and-dir-each_child.html">detailed blog</a>about it.</p><p>In Ruby 2.6, same methods are added as instance methods on <code>Dir</code> class.Dir#children (Link is not available) returns array of all the filenames except<code>.</code> and <code>..</code> in the directory. Dir#each_child (Link is not available) yields allthe filenames and operates on it.</p><p>Let's have a look at examples to understand it better.</p><h5>Dir#children</h5><pre><code class="language-ruby">directory = Dir.new('/Users/tejaswinichile/workspace')directory.children=&gt; [&quot;panda.png&quot;, &quot;apple.png&quot;, &quot;banana.png&quot;, &quot;camera.jpg&quot;]</code></pre><p><code>Dir#each_child</code> iterates and calls block for each file entry in the givendirectory. It uses filename as a parameter to the block.</p><h5>Dir#each_child</h5><pre><code class="language-ruby">directory = Dir.new('/Users/tejaswinichile/workspace')directory.each_child { |filename| puts &quot;Currently reading: #{filename}&quot;}Currently reading: panda.pngCurrently reading: apple.pngCurrently reading: banana.pngCurrently reading: camera.jpg=&gt; #&lt;Dir:/Users/tejaswinichile/Desktop&gt;</code></pre><p>If we don't pass any block to <code>each_child</code>, it returns enumerator instead.</p><pre><code class="language-ruby">directory = Dir.new('/Users/tejaswinichile/workspace')directory.each_child=&gt; #&lt;Enumerator: #&lt;Dir:/Users/tejaswinichile/Desktop&gt;:each_child&gt;</code></pre><p>Here is relevant<a href="https://github.com/ruby/ruby/commit/6a3a7e9114c3ede47d15f0d2a73f392cfcdd1ea7">commit</a>and <a href="https://bugs.ruby-lang.org/issues/13969">discussion</a> for this change.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds exception parameters for Integer & Float methods]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-adds-option-to-not-raise-exception-for-integer-float-methods"/>
      <updated>2018-07-31T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-adds-option-to-not-raise-exception-for-integer-float-methods</id>
      <content type="html"><![CDATA[<p>We can use <code>Integer</code> and <code>Float</code> methods to convert values to integers andfloats respectively. Ruby also has <code>to_i</code> and <code>to_f</code> methods for same purpose.Let's see how it differs from the <code>Integer</code> method.</p><pre><code class="language-ruby">&gt; &gt; &quot;1one&quot;.to_i&gt; &gt; =&gt; 1&gt; &gt; Integer(&quot;1one&quot;)&gt; &gt; ArgumentError: invalid value for Integer(): &quot;1one&quot;    from (irb):2:in `Integer'    from (irb):2    from /Users/prathamesh/.rbenv/versions/2.4.0/bin/irb:11:in `&lt;main&gt;'&gt; &gt;</code></pre><p>The <code>to_i</code> method tries to convert the given input to integer as much aspossible whereas the <code>Integer</code> method throws an <code>ArgumentError</code> if it can'tcovert the input to integer. The <code>Integer</code> and <code>Float</code> methods parse morestrictly compared to <code>to_i</code> and <code>to_f</code> respectively.</p><p>Some times, we might need the strictness of <code>Integer</code> and <code>Float</code> but ability tonot raise an exception every time the input can't be parsed.</p><p>Before Ruby 2.6 it was possible to achieve it in following way.</p><pre><code class="language-ruby">&gt; &gt; Integer(&quot;msg&quot;) rescue nil&gt; &gt;</code></pre><p>In Ruby 2.6, the<a href="https://bugs.ruby-lang.org/issues/12732">Integer and Float methods accept a keyword argument exception</a>which can be either <code>true</code> or <code>false</code>. If it is <code>false</code> then no exception israised if the input can't be parsed and <code>nil</code> is returned.</p><pre><code class="language-ruby">&gt; &gt; Float(&quot;foo&quot;, exception: false)&gt; &gt; =&gt; nil&gt; &gt; Integer(&quot;foo&quot;, exception: false)&gt; &gt; =&gt; nil&gt; &gt;</code></pre><p>This is also faster than rescuing the exception and returning <code>nil</code>.</p><pre><code class="language-ruby">&gt; &gt; Benchmark.ips do |x|&gt; &gt; ?&gt; x.report(&quot;rescue&quot;) {&gt; &gt; ?&gt; Integer('foo') rescue nil&gt; &gt; }&gt; &gt; x.report(&quot;kwarg&quot;) {&gt; &gt; ?&gt; Integer('foo', exception: false)&gt; &gt; }&gt; &gt; x.compare!&gt; &gt; end&gt; &gt; Warming up --------------------------------------              rescue    41.896k i/100ms               kwarg    81.459k i/100msCalculating -------------------------------------rescue 488.006k ( 4.5%) i/s - 2.472M in 5.076848skwarg 1.024M (11.8%) i/s - 5.050M in 5.024937sComparison:kwarg: 1023555.3 i/srescue: 488006.0 i/s - 2.10x slower</code></pre><p>As we can see, rescuing the exception is twice slower than using the new keywordargument. We can still use the older technique if we want to return a differentvalue from <code>nil</code>.</p><pre><code class="language-ruby">&gt; &gt; Integer('foo') rescue 42&gt; &gt; =&gt; 42&gt; &gt;</code></pre><p>By default, the keyword argument <code>exception</code> is set to <code>true</code> for backwardcompatibility.</p><p>The Chinese version of this blog is available<a href="http://madao.me/yi-ruby-2-6-zeng-jia-liao-integer-he-float-fang-fa-de-yi-chang-can-shu/">here</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds Binding#source_location]]></title>
       <author><name>Taha Husain</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-adds-binding-source-location"/>
      <updated>2018-07-24T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-adds-binding-source-location</id>
      <content type="html"><![CDATA[<p>Before Ruby 2.6, if we want to know file name with location and line number ofsource code, we would need to use Binding#eval (Link is not available) .</p><pre><code class="language-ruby">binding.eval('[__FILE__, __LINE__]')=&gt; [&quot;/Users/taha/blog/app/controllers/application_controller&quot;, 2]</code></pre><p>Ruby 2.6 adds more readable method Binding#source_location (Link is notavailable) to achieve similar result.</p><pre><code class="language-ruby">binding.source_location=&gt; [&quot;/Users/taha/blog/app/controllers/application_controller&quot;, 2]</code></pre><p>Here is relevant <a href="https://github.com/ruby/ruby/commit/571e48">commit</a> and<a href="https://bugs.ruby-lang.org/issues/14230">discussion</a> for this change.</p><p>The Chinese version of this blog is available<a href="http://madao.me/yi-ruby-2-6-binding-dui-xiang-zeng-jia-source_location-fang-fa/">here</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds String#split with block]]></title>
       <author><name>Taha Husain</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-adds-split-with-block"/>
      <updated>2018-07-17T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-adds-split-with-block</id>
      <content type="html"><![CDATA[<p>Before Ruby 2.6,<a href="http://ruby-doc.org/core-2.5.1/String.html#method-i-split">String#split</a>returned array of split strings.</p><p>In Ruby 2.6, a block can be passed to String#split (Link is not available) whichyields each split string and operates on it. This avoids creating an array andthus is memory efficient.</p><p>We will add method <code>is_fruit?</code> to understand how to use <code>split</code> with a block.</p><pre><code class="language-ruby">def is_fruit?(value)%w(apple mango banana watermelon grapes guava lychee).include?(value)end</code></pre><p>Input is a comma separated string with vegetables and fruits names. Goal is tofetch names of fruits from input string and store it in an array.</p><h5>String#split</h5><pre><code class="language-ruby">input_str = &quot;apple, mango, potato, banana, cabbage, watermelon, grapes&quot;splitted_values = input_str.split(&quot;, &quot;)=&gt; [&quot;apple&quot;, &quot;mango&quot;, &quot;potato&quot;, &quot;banana&quot;, &quot;cabbage&quot;, &quot;watermelon&quot;, &quot;grapes&quot;]fruits = splitted_values.select { |value| is_fruit?(value) }=&gt; [&quot;apple&quot;, &quot;mango&quot;, &quot;banana&quot;, &quot;watermelon&quot;, &quot;grapes&quot;]</code></pre><p>Using <code>split</code> an intermediate array is created which contains both fruits andvegetables names.</p><h5>String#split with a block</h5><pre><code class="language-ruby">fruits = []input_str = &quot;apple, mango, potato, banana, cabbage, watermelon, grapes&quot;input_str.split(&quot;, &quot;) { |value| fruits &lt;&lt; value if is_fruit?(value) }=&gt; &quot;apple, mango, potato, banana, cabbage, watermelon, grapes&quot;fruits=&gt; [&quot;apple&quot;, &quot;mango&quot;, &quot;banana&quot;, &quot;watermelon&quot;, &quot;grapes&quot;]</code></pre><p>When a block is passed to <code>split</code>, it returns the string on which split wascalled and does not create an array. <code>String#split</code> yields block on each splitstring, which in our case was to push fruit names in a separate array.</p><h4>Update</h4><h5>Benchmark</h5><p>We created a large random string to benchmark performance of <code>split</code> and<code>split with block</code></p><pre><code class="language-ruby">require 'securerandom'test_string = ''100_000.times.each dotest_string += SecureRandom.alphanumeric(10)test_string += ' 'end</code></pre><pre><code class="language-ruby">require 'benchmark'Benchmark.bmbm do |bench|bench.report('split') doarr = test_string.split(' ')str_starts_with_a = arr.select { |str| str.start_with?('a') }endbench.report('split with block') dostr_starts_with_a = []test_string.split(' ') { |str| str_starts_with_a &lt;&lt; str if str.start_with?('a') }endend</code></pre><p>Results</p><pre><code class="language-plaintext">Rehearsal ----------------------------------------------------split              0.023764   0.000911   0.024675 (  0.024686)split with block   0.012892   0.000553   0.013445 (  0.013486)------------------------------------------- total: 0.038120sec                       user     system      total        realsplit              0.024107   0.000487   0.024594 (  0.024622)split with block   0.010613   0.000334   0.010947 (  0.010991)</code></pre><p>We did another iteration of benchmarking using<a href="https://github.com/evanphx/benchmark-ips">benchmark/ips</a>.</p><pre><code class="language-ruby">require 'benchmark/ips'Benchmark.ips do |bench|bench.report('split') dosplitted_arr = test_string.split(' ')str_starts_with_a = splitted_arr.select { |str| str.start_with?('a') }endbench.report('split with block') dostr_starts_with_a = []test_string.split(' ') { |str| str_starts_with_a &lt;&lt; str if str.start_with?('a') }endbench.compare!end</code></pre><p>Results</p><pre><code class="language-plaintext">Warming up --------------------------------------               split     4.000  i/100ms    split with block    10.000  i/100msCalculating -------------------------------------               split     46.906  ( 2.1%) i/s -    236.000  in   5.033343s    split with block    107.301  ( 1.9%) i/s -    540.000  in   5.033614sComparison:    split with block:      107.3 i/s               split:       46.9 i/s - 2.29x  slower</code></pre><p>This benchmark shows that <code>split with block</code> is about 2 times faster than<code>split</code>.</p><p>Here is relevant<a href="https://github.com/ruby/ruby/commit/2258a97fe2b21da9ec294ccedd00b3bbbc85cb07">commit</a>and <a href="https://bugs.ruby-lang.org/issues/4780">discussion</a> for this change.</p><p>The Chinese version of this blog is available<a href="http://madao.me/yi-ruby-2-6-stringde-split-fang-fa-zhi-chi-dai-ma-kuai-zhi-xing/">here</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 raises exception for else without rescue]]></title>
       <author><name>Rohan Pujari</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2.6-raise-exception-for-else-without-rescue"/>
      <updated>2018-07-10T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2.6-raise-exception-for-else-without-rescue</id>
      <content type="html"><![CDATA[<h4>Ruby 2.5</h4><p>If we use <code>else</code> without <code>rescue</code> inside <code>begin..end</code> block in Ruby 2.5, itgives a warning.</p><pre><code class="language-ruby">irb(main):001:0&gt; beginirb(main):002:1&gt; puts &quot;Inside begin block&quot;irb(main):003:1&gt; elseirb(main):004:1&gt; puts &quot;Inside else block&quot;irb(main):005:1&gt; end(irb):5: warning: else without rescue is useless</code></pre><p>This warning is present as code inside <code>else</code> block will never get executed</p><h4>Ruby 2.6</h4><p>In Ruby 2.6 it will raise an exception if we use <code>else</code> without <code>rescue</code> in<code>begin..end</code> block. This<a href="https://github.com/ruby/ruby/commit/140512d2225e6fd046ba1bdbcd1a27450f55c233#diff-ff4e2dc4962dc25a1512353299992c8d">commit</a>changed warning into exception in Ruby 2.6. Changes made in the commit areexperimental.</p><pre><code class="language-ruby">irb(main):001:0&gt; beginirb(main):002:1&gt; puts &quot;Inside begin block&quot;irb(main):003:1&gt; elseirb(main):004:1&gt; puts &quot;Inside else block&quot;irb(main):005:1&gt; endTraceback (most recent call last):1: from /usr/local/bin/irb:11:in `&lt;main&gt;'SyntaxError ((irb):3: else without rescue is useless)</code></pre><p>The Chinese version of this blog is available<a href="http://madao.me/yi-ruby-2-6-hui-zai-begin-end-dai-ma-kuai-zhong-yin-wei-bu-xie-rescue-zhi-xie-else-er-pao-chu-yi-chang-shi-yan-xing-feature">here</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 adds endless range]]></title>
       <author><name>Taha Husain</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-adds-endless-range"/>
      <updated>2018-07-04T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-adds-endless-range</id>
      <content type="html"><![CDATA[<p>Before Ruby 2.6, if we want endless loop with index, we would need to use<a href="http://ruby-doc.org/core-2.5.1/Float.html#INFINITY">Float::INFINITY</a> with<a href="http://ruby-doc.org/core-2.5.1/Integer.html#method-i-upto">up to</a> or<a href="http://ruby-doc.org/core-2.5.1/Range.html">Range</a>, or use<a href="http://ruby-doc.org/core-2.5.1/Numeric.html#method-i-step">Numeric#step</a>.</p><h5>Ruby 2.5.0</h5><pre><code class="language-ruby">irb&gt; (1..Float::INFINITY).each do |n|irb\* # logic goes hereirb&gt; end</code></pre><p>OR</p><pre><code class="language-ruby">irb&gt; 1.step.each do |n|irb\* # logic goes hereirb&gt; end</code></pre><h4>Ruby 2.6.0</h4><p>Ruby 2.6 makes infinite loop more readable by changing mandatory second argumentin range to optional. Internally, Ruby changes second argument to <code>nil</code> ifsecond argument is not provided. So, both <code>(0..)</code> and <code>(0..nil)</code> are same inRuby 2.6.</p><h6>Using endless loop in Ruby 2.6</h6><pre><code class="language-ruby">irb&gt; (0..).each do |n|irb\* # logic goes hereirb&gt; end</code></pre><pre><code class="language-ruby">irb&gt; (0..nil).size=&gt; Infinityirb&gt; (0..).size=&gt; Infinity</code></pre><p>In Ruby 2.5, <code>nil</code> is not an acceptable argument and <code>(0..nil)</code> would throw<code>ArgumentError</code>.</p><pre><code class="language-ruby">irb&gt; (0..nil)ArgumentError (bad value for range)</code></pre><p>Here is the relevant<a href="https://github.com/ruby/ruby/commit/7f95eed19e22cb9a4867819355fe4ab99f85fd16">commit</a>and <a href="https://bugs.ruby-lang.org/issues/12912">discussion</a> for this change.</p><p>The Chinese version of this blog is available<a href="http://madao.me/yi-ruby-2-6-zeng-jia-wu-qiong-fan-wei/">here</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 2.6 added option to raise exception in Kernel#system]]></title>
       <author><name>Amit Choudhary</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-2-6-added-option-to-raise-exception-in-kernel-system"/>
      <updated>2018-04-25T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-2-6-added-option-to-raise-exception-in-kernel-system</id>
      <content type="html"><![CDATA[<p>We write scripts to automate setup and deployment of Rails applications. Inthose scripts, in many places, we need to run system commands like<code>bundle install</code>, <code>rake db:create</code>, <code>rake db:migrate</code> and many more.</p><p>Let's suppose we need to run migrations using <code>rake db:migrate</code> in a Railsproject setup script. We can use the <code>Kernel#system</code> method.</p><pre><code class="language-ruby">irb&gt; system('rake db:migrate')</code></pre><h4>Ruby 2.5.0</h4><p>Executing <code>system</code> returns <code>true</code> or <code>false</code>. Another feature of <code>system</code> isthat it eats up the exceptions.</p><p>Let's suppose our migrations can run successfully. In this case the <code>system</code>command for running migrations will return true.</p><pre><code class="language-ruby">irb&gt; system('rake db:migrate') =&gt; true</code></pre><p>Let's suppose we have a migration that is trying to add a column to a tablewhich does not exist. In this case, the <code>system</code> command for running migrationswill return false.</p><pre><code class="language-ruby">irb&gt; system('rake db:migrate')== 20180311211836 AddFirstNameToAdmins: migrating =============================-- add_column(:admins, :first_name, :string)rake aborted!StandardError: An error has occurred, this and all later migrations canceled:PG::UndefinedTable: ERROR:  relation &quot;admins&quot; does not exist: ALTER TABLE &quot;admins&quot; ADD &quot;first_name&quot; character varying...Tasks: TOP =&gt; db:migrate(See full trace by running task with --trace) =&gt; false</code></pre><p>As we can see, even when there is a failure in executing system commands, thereturn value is false. Ruby does not raise an exception in those cases.</p><p>However, we can use <code>raise</code> explicitly to raise an exception and halt the setupscript execution.</p><pre><code class="language-ruby">irb&gt; system('rake db:migrate') || raise('Failed to run migrations')== 20180311211836 AddFirstNameToAdmins: migrating =============================-- add_column(:admins, :first_name, :string)rake aborted!StandardError: An error has occurred, this and all later migrations canceled:PG::UndefinedTable: ERROR:  relation &quot;admins&quot; does not exist: ALTER TABLE &quot;admins&quot; ADD &quot;first_name&quot; character varying...Tasks: TOP =&gt; db:migrate(See full trace by running task with --trace)Traceback (most recent call last):        2: from /Users/amit/.rvm/rubies/ruby-2.5.0/bin/irb:11:in `&lt;main&gt;'        1: from (irb):4RuntimeError (Failed to run migrations)</code></pre><h4>Ruby 2.6.0-preview1</h4><p>Ruby 2.6 make our lives easier by providing an option <code>exception: true</code> so thatwe do not need to use <code>raise</code> explicitly to halt script execution.</p><pre><code class="language-ruby">irb&gt; system('rake db:migrate', exception: true)== 20180311211836 AddFirstNameToAdmins: migrating =============================-- add_column(:admins, :first_name, :string)rake aborted!StandardError: An error has occurred, this and all later migrations canceled:PG::UndefinedTable: ERROR:  relation &quot;admins&quot; does not exist: ALTER TABLE &quot;admins&quot; ADD &quot;first_name&quot; character varying...Tasks: TOP =&gt; db:migrate(See full trace by running task with --trace)Traceback (most recent call last):        3: from /Users/amit/.rvm/rubies/ruby-2.6.0-preview1/bin/irb:11:in `&lt;main&gt;'        2: from (irb):2        1: from (irb):2:in `system'RuntimeError (Command failed with exit 1: rake)</code></pre><p>Ruby 2.6 works the same way as previous Ruby versions when used without the<code>exception</code> option or used with <code>exception</code> set as false.</p><pre><code class="language-ruby">irb&gt; system('rake db:migrate', exception: false)== 20180311211836 AddFirstNameToAdmins: migrating =============================-- add_column(:admins, :first_name, :string)rake aborted!StandardError: An error has occurred, this and all later migrations canceled:PG::UndefinedTable: ERROR:  relation &quot;admins&quot; does not exist: ALTER TABLE &quot;admins&quot; ADD &quot;first_name&quot; character varying...Tasks: TOP =&gt; db:migrate(See full trace by running task with --trace) =&gt; false</code></pre><p>Here is the relevant <a href="https://github.com/ruby/ruby/commit/fb29cffab0">commit</a>and <a href="https://bugs.ruby-lang.org/issues/14386">discussion</a> for this change.</p><p><code>system</code> is not the only way to execute scripts like these. We wrote<a href="https://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html">a blog</a>6 years ago which discusses the differences between running commands using<code>backtick</code>, <code>exec</code>, <code>sh</code>, <code>popen3</code>, <code>popen2e</code> and <code>Process.spawn</code>.</p><p>The Chinese version of this blog is available<a href="http://madao.me/yi-ruby-2-6-kernel-de-system-fang-fa-zeng-jia-shi-fou-pao-chu-yi-chang-can-shu/">here</a>.</p>]]></content>
    </entry>
     </feed>