<?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom">
     <title>BigBinary Blog</title>
     <link href="https://www.bigbinary.com/feed.xml" rel="self"/>
     <link href="https://www.bigbinary.com/"/>
     <updated>2026-06-08T04:59:46+00:00</updated>
     <id>https://www.bigbinary.com/</id>
     <entry>
       <title><![CDATA[Ruby 3 is released - The list of Ruby 3 features]]></title>
       <author><name>Datt Dongare</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-3-features"/>
      <updated>2020-12-25T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-3-features</id>
      <content type="html"><![CDATA[<p>For all Rubyists, <strong>2020</strong> was a special year. Why wouldn't it be? Ruby 2 wasreleased in 2013. We have been using Ruby 2.x for almost 7 years and we havebeen waiting to see Ruby 3 get released. Finally, the wait is over now.<a href="https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/">Ruby 3.0.0 has been released</a>.It's time to unwrap the gift box and see all the Ruby 3 features we got.</p><h2>Ruby 3 major updates</h2><p>The number <strong>3</strong> is very significant in the Ruby 3 release. Be it releaseversion number, making performance 3x faster, or the trio of corecontributors(Matz, TenderLove, Koichi). Similarly, there were 3 major goals ofRuby 3: being faster, having better concurrency, and ensuring correctness.</p><p><img src="/blog_images/2020/ruby-3-features/ruby-3-features.jpg" alt="Ruby 3 features"></p><h3>1. Ruby 3 performance</h3><p>One of the major focuses for Ruby 3 was the performance. In fact, the initialdiscussion for Ruby 3 was started around it. Matz had set a very ambitious goalof making Ruby 3 times faster.</p><h4>What is Ruby 3x3?</h4><p>Before discussing this, let's revisit Ruby's core philosophy.</p><blockquote><p>&quot;I hope to see Ruby help every programmer in the world to be productive, andto enjoy programming, and to be happy.&quot; - Matz</p></blockquote><p>About Ruby 3x3, some asked whether the goal was to make Ruby the fastestlanguage? The answer is no. The main goal of Ruby 3x3 was to make Ruby 3 timesfaster than Ruby 2.</p><blockquote><p>No language is fast enough. - Matz</p></blockquote><p>Ruby was not designed to be fastest and if it would have been the goal, Rubywouldn't be the same as it is today. As Ruby language gets performance boost, itdefinitely helps our application be faster and scalable.</p><blockquote><p>&quot;In the design of the Ruby language we have been primarily focused onproductivity and the joy of programming. As a result, Ruby was too slow.&quot; -Matz</p></blockquote><p>There are two areas where performance can be measured: memory and CPU.</p><h4>CPU optimization</h4><p>Some enhancements in Ruby internals have been made to improve the speed. TheRuby team has optimized the JIT(Just In Time) compiler from previous versions.<a href="https://bigbinary.com/blog/mjit-support-in-ruby-2-6">Ruby MJIT compiler</a> wasfirst introduced in Ruby 2.6. Ruby 3 MJIT comes with better security and seemsto improve web apps performance to a greater extent.</p><p><img src="/blog_images/2020/ruby-3-features/machine-performance.jpg" alt="CPU optimization"></p><p>MJIT implementation is different from the usual JIT. When methods get calledrepeatedly e.g. 10000 times, MJIT will pick such methods which can be compiledinto native code and put them into a queue. Later MJIT will fetch the queue andconvert them to native code.</p><p>Please check<a href="https://engineering.appfolio.com/appfolio-engineering/2019/7/18/jit-and-rubys-mjit">JIT vs MJIT</a>for more details.</p><h4>Memory optimization</h4><p>Ruby 3 comes with an enhanced garbage collector. It has python's buffer-like APIwhich helps in better memory utilization. Since Ruby 1.8, Ruby has continuouslyevolved in<a href="https://scoutapm.com/blog/ruby-garbage-collection">Garbage collection</a>algorithms.</p><h5>Automatic Garbage Compaction</h5><p>The latest change in garbage collection is<a href="https://engineering.appfolio.com/appfolio-engineering/2019/3/22/ruby-27-and-the-compacting-garbage-collector">Garbage Compaction</a>.It was introduced in Ruby 2.7 where the process was a bit manual. But in version3 it is fully automatic. The compactor is invoked aptly to make sure propermemory utilization.</p><h5>Objects Grouping</h5><p>The garbage compactor moves objects in the heap. It groups dispersed objectstogether at a single place in the memory so that this memory can be used even byheavier objects later.</p><p><img src="/blog_images/2020/ruby-3-features/binary-background.jpg" alt="Memory optimization"></p><h3>2. Parallelism and Concurrency in Ruby 3</h3><p>Concurrency is one of the important aspects of any programming language. Matzfeels that Threads are not the right level of abstraction for Ruby programmersto use.</p><blockquote><p>I regret adding Threads. - Matz</p></blockquote><p>Ruby 3 makes it a lot easier to make applications where concurrency is a majorfocus. There are several features and improvements added in Ruby 3 related toconcurrency.</p><h4>Fibers</h4><p>Fibers are considered a disruptive addition in Ruby 3. Fibers are light-weightworkers which appear like Threads but have some advantages. It consumes lessmemory than Threads. It gives greater control to the programmer to define codesegments that can be paused or resumed resulting in better I/O handling.</p><p><a href="https://github.com/socketry/falcon">Falcon Rack web server</a> uses Async Fibersinternally. This allows Falcon to not block on I/O. Asynchronously managing I/Ogives a great uplift to the Falcon server to serve requests concurrently.</p><h5>Fiber Scheduler</h5><p><a href="https://bugs.ruby-lang.org/issues/16786">Fiber Scheduler</a> is an experimentalfeature added in Ruby 3. It was introduced to intercept blocking operations suchas I/O. The best thing is that it allows lightweight concurrency and can easilyintegrate into the existing codebase without changing the original logic. It'san interface and that can be implemented by creating a wrapper for a gem like<code>EventMachine</code> or <code>Async</code>. This interface design allows separation of concernsbetween the event loop implementation and the application code.</p><p>Following is an example to send multiple <code>HTTP</code> requests concurrently using<code>Async</code>.</p><pre><code class="language-ruby">require 'async'require 'net/http'require 'uri'LINKS = [  'https://bigbinary.com',  'https://basecamp.com']Async do  LINKS.each do |link|    Async do      Net::HTTP.get(URI(link))    end  endend</code></pre><p>Please check <a href="https://github.com/ruby/ruby/blob/master/doc/fiber.md">fibers</a> formore details.</p><h4>Ractors (Guilds)</h4><p>As we know Rubys global <code>VM lock (GVL)</code> prevents most Ruby Threads fromcomputing in parallel.<a href="https://github.com/ruby/ruby/blob/master/doc/ractor.md">Ractors</a> work aroundthe <code>GVL</code> to offer better parallelism. Ractor is an Actor-Model like concurrentabstraction designed to provide a parallel execution without thread-safetyconcerns.</p><p>Ractors allows Threads in different Ractors to compute at the same time. EachRactor has at least one thread, which may contain multiple fibers. In a Ractor,only a single thread is allowed to execute at a given time.</p><p>The following program returns the square root of a really large number. Itcalculates the result for both numbers in parallel.</p><pre><code class="language-ruby"># Math.sqrt(number) in ractor1, ractor2 run in parallelractor1, ractor2 = *(1..2).map do  Ractor.new do    number = Ractor.recv    Math.sqrt(number)  endend# send parametersractor1.send 3**71ractor2.send 4**51p ractor1.take #=&gt; 8.665717809264115e+16p ractor2.take #=&gt; 2.251799813685248e+15</code></pre><h3>3. Static Analysis</h3><p>We need tests to ensure correctness of our program. However by its very naturetests could mean code duplication.</p><blockquote><p>I hate tests because they aren't DRY. - Matz</p></blockquote><p>To ensure the correctness of a program, static analysis can be a great tool inaddition to tests.</p><p>The static analysis relies on inline type annotations which aren't DRY. Thesolution to address this challenge is having <code>.rbs</code> files parallel to our <code>.rb</code>files.</p><h4>RBS</h4><p>RBS is a language to describe the structure of a Ruby program. It provides us anoverview of the program and how overall classes, methods, etc. are defined.Using RBS, we can write the definition of Ruby classes, modules, methods,instance variables, variable types, and inheritance. It supports commonly usedpatterns in Ruby code, and advanced types like unions and duck typing.</p><p>The <code>.rbs</code> files are something similar to <code>.d.ts</code> files in TypeScript. Followingis a small example of how a <code>.rbs</code> file looks like. The advantage of having atype definition is that it can be validated against both implementation andexecution.</p><p>The below example is pretty self-explanatory. One thing we can note here though,<code>each_post</code> accepts a block or returns an enumerator.</p><pre><code class="language-ruby"># user.rbsclass User  attr_reader name: String  attr_reader email: String  attr_reader age: Integer  attr_reader posts: Array[Post]  def initialize: (name: String,                   email: String,                   age: Integer) -&gt; void  def each_post: () { (Post) -&gt; void } -&gt; void                   | () -&gt; Enumerator[Post, void]end</code></pre><p>Please check <a href="https://github.com/ruby/rbs">RBS gem documentation</a> for moredetails.</p><h4>Typeprof</h4><p>Introducing type definition was a challenge because there is already a lot ofexisting Ruby code around and we need a tool that could automatically generatethe type signature. Typeprof is a type analysis tool that reads plain Ruby codeand generates a prototype of type signature in RBS format by analyzing themethods, and its usage. Typeprof is an experimental feature. Right now onlysmall subset of ruby is supported.</p><blockquote><p>Ruby is simple in appearance, but is very complex inside, just like our humanbody. - Matz</p></blockquote><p>Let's see an example.</p><pre><code class="language-ruby"># user.rbclass User  def initialize(name:, email:, age:)    @name, @email, @age = name, email, age  end  attr_reader :name, :email, :ageendUser.new(name: &quot;John Doe&quot;, email: 'john@example.com', age: 23)</code></pre><p>Output</p><pre><code class="language-ruby">$ typeprof user.rb# Classesclass User  attr_reader name : String  attr_reader email : String  attr_reader age : Integer  def initialize : (name: String,                    email: String,                    age: Integer) -&gt; [String, String, Integer]end</code></pre><h2>Other Ruby 3 features and changes</h2><p>In the 7-year period, the Ruby community has seen significant improvement inperformance and other aspects. Apart from major goals, Ruby 3 is an excitingupdate with lots of new features, handy syntactic changes, and new enhancements.In this section, we will discuss some notable features.</p><blockquote><p>We are making Ruby even better. - Matz</p></blockquote><h3>One-line pattern matching syntax change</h3><p>Previously one-line pattern matching used the keyword <code>in</code>. Now it's replacedwith <code>=&gt;</code>.</p><h6>Ruby 2.7</h6><pre><code class="language-ruby">  { name: 'John', role: 'CTO' } in {name:}  p name # =&gt; 'John'</code></pre><h6>Ruby 3.0</h6><pre><code class="language-ruby">  { name: 'John', role: 'CTO' } =&gt; {name:}  p name # =&gt; 'John'</code></pre><h3>Find pattern</h3><p>The<a href="https://github.com/ruby/ruby/blob/9738f96fcfe50b2a605e350bdd40bd7a85665f54/test/ruby/test_pattern_matching.rb">find pattern</a>was introduced in <code>Ruby 2.7</code> as an experimental feature. This is now part of<code>Ruby 3.0</code>. It is similar to pattern matching in <code>Elixir</code> or <code>Haskell</code>.</p><pre><code class="language-ruby">users = [  { name: 'Oliver', role: 'CTO' },  { name: 'Sam', role: 'Manager' },  { role: 'customer' },  { name: 'Eve', city: 'New York' },  { name: 'Peter' },  { city: 'Chicago' }]users.each do |person|  case person  in { name:, role: 'CTO' }    p &quot;#{name} is the Founder.&quot;  in { name:, role: designation }    p &quot;#{name} is a #{designation}.&quot;  in { name:, city: 'New York' }    p &quot;#{name} lives in New York.&quot;  in {role: designation}    p &quot;Unknown is a #{designation}.&quot;  in { name: }    p &quot;#{name}'s designation is unknown.&quot;  else    p &quot;Pattern not found.&quot;  endend&quot;Oliver is the Founder.&quot;&quot;Sam is a Manager.&quot;&quot;Unknown is a customer.&quot;&quot;Eve lives in New York.&quot;&quot;Peter's designation is unknown.&quot;&quot;Pattern not found.&quot;</code></pre><h3>Endless Method definition</h3><p>This is another syntax enhancement that is optional to use. It enables us tocreate method definitions<a href="https://bigbinary.com/blog/ruby-3-adds-endless-method-definition">without end keyword</a>.</p><pre><code class="language-ruby">def: increment(x) = x + 1p increment(42) #=&gt; 43</code></pre><h3>Except method in Hash</h3><p>Sometimes while working on a non Rails app I get <code>undefined method except</code>. The<code>except</code> method was available only in Rails. In Ruby 3 <code>Hash#except</code> was<a href="https://bigbinary.com/blog/ruby-3-adds-new-method-hash-except">added to Ruby</a>itself.</p><pre><code class="language-ruby">user = { name: 'Oliver', age: 29, role: 'CTO' }user.except(:role) #=&gt; {:name=&gt; &quot;Oliver&quot;, :age=&gt; 29}</code></pre><h3>Memory View</h3><p>This is again an experimental feature. This is a C-API that will allow extensionlibraries to exchange raw memory area. Extension libraries can also sharemetadata of memory area that consists of shape and element format. It wasinspired by<a href="https://docs.python.org/3/c-api/buffer.html">Pythons buffer protocol</a>.</p><h3>Arguments forwarding</h3><p>Arguments forwarding <code>(...)</code> now supports leading arguments.</p><p>It is helpful in <code>method_missing</code>, where we need method name as well.</p><pre><code class="language-ruby">def method_missing(name, ...)  if name.to_s.end_with?('?')    self[name]  else    fallback(name, ...)  endend</code></pre><h3>Other Notable changes</h3><ul><li>Pasting in IRB is much faster.</li><li>The order of backtrace had been<a href="https://bigbinary.com/blog/ruby-2-5-prints-backstrace-and-error-message-in-reverse-order">reversed</a>.The error message and line number are printed first, rest of the backtrace isprinted later.</li><li><a href="https://bigbinary.com/blog/ruby-3-supports-transforming-hash-keys-using-a-hash-argument">Hash#transform_keys</a>accepts a hash that maps old keys with new keys.</li><li>Interpolated String literals are no longer frozen when<code># frozen-string-literal: true</code> is used.</li><li>Symbol#to_proc now returns a lambda Proc.</li><li><a href="https://bigbinary.com/blog/ruby-3-adds-symbol-name">Symbol#name</a> has beenadded, which returns the symbol's name as a frozen string.</li></ul><p>Many other changes can be checked at<a href="https://github.com/ruby/ruby/blob/v3_0_0_preview2/NEWS.md">Ruby 3 News</a> formore details.</p><h2>Transition</h2><p>A lot of core libraries have been modified to fit the Ruby 3 goal needs. Butthis doesn't mean that our old applications will suddenly stop working. The Rubyteam has made sure that these changes are backward compatible. We might see somedeprecation warnings in our existing code. The developers can fix these warningsto smoothly transition from an old version to the new version. We are all set touse new features and get all new performance improvements.</p><h2>Conclusion</h2><p>With great improvements in performance, memory utilization, static analysis, andnew features like Ractors and schedulers, we have great confidence in the futureof Ruby. With Ruby 3, the applications can be more scalable and more enjoyableto work with. The coming 2021 is not just a new year but rather a new era forall Rubyists. We at BigBinary thank everyone who contributed towards the Ruby 3release directly or indirectly.</p><p>Happy Holidays and Happy New Year folks!!!</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 3 supports transforming hash keys using a hash argument]]></title>
       <author><name>Yedhin Kizhakkethara</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-3-supports-transforming-hash-keys-using-a-hash-argument"/>
      <updated>2020-12-15T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-3-supports-transforming-hash-keys-using-a-hash-argument</id>
      <content type="html"><![CDATA[<p>From Ruby 3 onwards, the <code>Hash#transform_keys</code> methodaccepts a hash argument for transformingexisting keys to new keys as specified in the argument.</p><h5>Usage before Ruby 3</h5><p>The following example shows how we used to apply <code>transform_keys</code>:</p><pre><code class="language-ruby"># 1. Declare address hashirb(main)&gt; address = {House: 'Kizhakkethara', house_no: 123, locality: 'India'}=&gt; {:House=&gt;&quot;Kizhakkethara&quot;, :house_no=&gt;123, :locality=&gt;&quot;India&quot;}# 2. Lowercase all the keysirb(main)&gt; address.transform_keys(&amp;:downcase)=&gt; {:house=&gt;&quot;Kizhakkethara&quot;, :house_no=&gt;123, :locality=&gt;&quot;India&quot;}# 3. Replace a particular key with a new key along with lowercasingirb(main)* address.transform_keys do |key|irb(main)*   new_key = keyirb(main)*   if key == :localityirb(main)*     new_key = :countryirb(main)*   endirb(main)*   new_key.to_s.downcase.to_symirb(main)&gt; end=&gt; {:house=&gt;&quot;Kizhakkethara&quot;, :house_no=&gt;123, :country=&gt;&quot;India&quot;}</code></pre><p>Although the changes required are trivial,we ended up writing a block to do the job.But what happens when the number of keysthat needs to be transformed increases?Do we need to write n-number of conditions within a block?Not anymore!</p><h5>Introducing Hash#transform_keys with hash argument</h5><p>Let's take the same example and provide a hash,which will be used for the transformation:</p><pre><code class="language-ruby"># 1. Declare address hashirb(main)&gt; address = {House: 'Kizhakkethara', house_no: 123, locality: 'India'}=&gt; {:House=&gt;&quot;Kizhakkethara&quot;, :house_no=&gt;123, :locality=&gt;&quot;India&quot;}# 2. Provide hash with transform_keysirb(main)&gt; address.transform_keys({House: :house, locality: :country})=&gt; {:house=&gt;&quot;Kizhakkethara&quot;, :house_no=&gt;123, :country=&gt;&quot;India&quot;}</code></pre><p>That does the job.But let's try to improve this code.Ultimately what happens when we invoke that methodis that it goes througheach of the keys in our variableandmaps the existing keys to the new keys.The <code>transform_keys</code> method accepts a block as a parameter.Thus let's pass in the <code>downcase</code> method as a <code>Proc</code> argument:</p><pre><code class="language-ruby"># 1. Passing in block parametersirb(main)&gt; address.transform_keys({locality: :country}, &amp;:downcase)=&gt; {:house=&gt;&quot;Kizhakkethara&quot;, :house_no=&gt;123, :country=&gt;&quot;India&quot;}</code></pre><p>An important point to be noted about the block parameter is that,<strong>it's only applied to keys which are not specified in the hash argument</strong>.</p><h3>Other common use cases</h3><h5>Transforming params received in the Rails controller</h5><pre><code class="language-ruby"># 1. Declare paramsirb(rails)&gt; params = ActionController::Parameters.new({&quot;firstName&quot;=&gt;&quot;oliver&quot;, &quot;lastName&quot;=&gt;&quot;smith&quot;, &quot;email&quot;=&gt;&quot;oliver@bigbinary.com&quot;})=&gt; &lt;ActionController::Parameters {&quot;firstName&quot;=&gt;&quot;oliver&quot;, &quot;lastName&quot;=&gt;&quot;smith&quot;, &quot;email&quot;=&gt;&quot;oliver@bigbinary.com&quot;} permitted: false&gt;# 2. Convert camelCase to snake_case using block parameterirb(rails)&gt; params.permit(:firstName, :lastName, :email).transform_keys(&amp;:underscore)=&gt; &lt;ActionController::Parameters {&quot;first_name&quot;=&gt;&quot;oliver&quot;, &quot;last_name&quot;=&gt;&quot;smith&quot;, &quot;email&quot;=&gt;&quot;oliver@bigbinary.com&quot;} permitted: true&gt;# 3. Or using hash argumentirb(rails)&gt; params.permit(:firstName, :lastName, :email).transform_keys({firstName: 'first_name', lastName: 'last_name'})=&gt; &lt;ActionController::Parameters {&quot;first_name&quot;=&gt;&quot;oliver&quot;, &quot;last_name&quot;=&gt;&quot;smith&quot;, &quot;email&quot;=&gt;&quot;oliver@bigbinary.com&quot;} permitted: true&gt;</code></pre><h5>Slicing hash along with key transformation</h5><pre><code class="language-ruby">irb(main)&gt; address.transform_keys({locality: :country}).slice(:house_no, :country)=&gt; {:house_no=&gt;123, :country=&gt;&quot;India&quot;}</code></pre><h5>Transforming keys in place using bang counterpart</h5><pre><code class="language-ruby">irb(main)&gt; address.transform_keys!({locality: :country}, &amp;:downcase)irb(main)&gt; address=&gt; {:house=&gt;&quot;Kizhakkethara&quot;, :house_no=&gt;123, :country=&gt;&quot;India&quot;}</code></pre><h5>References</h5><ul><li>Discussions regarding this feature can be found<a href="https://bugs.ruby-lang.org/issues/16274?tab=history">here</a>.</li><li>Commit for this feature can be found<a href="https://github.com/ruby/ruby/commit/b25e27277dc39f25cfca4db8452d254f6cc8046e">here</a>.</li></ul>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 3 adds new method Hash#except]]></title>
       <author><name>Akhil Gautam</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-3-adds-new-method-hash-except"/>
      <updated>2020-11-11T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-3-adds-new-method-hash-except</id>
      <content type="html"><![CDATA[<p>Ruby 3 addsa new method, <code>except</code>, to the Hash class.<code>Hash#except</code> returns a hashexcluding the given keysandtheir values.</p><h3>Why do we need Hash#except?</h3><p>At times,we needto print or log everythingexcept some sensitive data.Let's saywe want to printuser detailsin the logsbut not passwords.</p><p>Before Ruby 3 we could have achievedit in the following ways:</p><pre><code class="language-ruby">irb(main):001:0&gt; user_details = { name: 'Akhil', age: 25, address: 'India', password: 'T:%g6R' }# 1. Reject with a block and include?irb(main):003:0&gt; puts user_details.reject { |key, _| key == :password }=&gt; { name: 'Akhil', age: 25, address: 'India' }# 2. Clone the hash with dup, tap into it and delete that key/value from the cloneirb(main):005:0&gt; puts user_details.dup.tap { |hash| hash.delete(:password) }=&gt; { name: 'Akhil', age: 25, address: 'India' }</code></pre><p>We know that ActiveSupport alreadycomes with <code>Hash#except</code>but for a simple Ruby applicationusing ActiveSupport wouldbe overkill.</p><h3>Ruby 3</h3><p>To make the above taskeasier and more explicit,Ruby 3 adds <code>Hash#except</code>to return a hashexcluding the given keys and their values:</p><pre><code class="language-ruby">irb(main):001:0&gt; user_details = { name: 'Akhil', age: 25, address: 'India', password: 'T:%g6R' }irb(main):002:0&gt; puts user_details.except(:password)=&gt; { name: 'Akhil', age: 25, address: 'India' }irb(main):003:0&gt; db_info = YAML.safe_load(File.read('./database.yml'))irb(main):004:0&gt; puts db_info.except(:username, :password)=&gt; { port: 5432, database_name: 'example_db_production' }</code></pre><p>Check out the<a href="https://github.com/ruby/ruby/commit/82ca8c73034b0a522fd2970ea39edfcd801955fe">commit</a>for more details.Discussion around it can be found <a href="https://bugs.ruby-lang.org/issues/15822">here</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 3 adds Symbol#name]]></title>
       <author><name>Datt Dongare</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-3-adds-symbol-name"/>
      <updated>2020-10-12T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-3-adds-symbol-name</id>
      <content type="html"><![CDATA[<p>All are excited aboutwhat <code>Ruby 3.0</code> hasto offer to the Ruby developers.There is already a lot of buzzthat the feature set of <code>Ruby 3.0</code>will change the perspective of developershow they look at <code>Ruby</code>.</p><p>One of the important aspects of <code>Ruby 3.0</code> is optimization.The part of that optimization isthe introduction of <code>name</code> method for <code>Symbol</code>.In this blog,we will take a lookat what <code>name</code> method of class <code>Symbol</code> doesandwhy it was introduced.The new <code>name</code> method is introduced on <code>Symbol</code>to simply convert a symbol into a string.<code>Symbol#name</code> returns a string.Let's see how it works.</p><pre><code class="language-ruby">irb(main):001:0&gt; :simba.name=&gt; 'simba'irb(main):002:0&gt; :simba.name.class=&gt; Stringirb(main):003:0&gt; :simba.name === :simba.name=&gt; true</code></pre><p>Wait what?Don't we have <code>to_s</code>to convert a symbol into a string.Most of us have used <code>to_s</code> method on a <code>Symbol</code>.The <code>to_s</code> method returns a <code>String</code> objectandwe can simply use it.But why <code>name</code>?</p><p>Using <code>to_s</code> is okay in most cases.But the problem with <code>to_s</code> isthat it creates a new <code>String</code> objectevery time we call it on a symbol.We can verify this in <code>irb</code>.</p><pre><code class="language-ruby">irb(main):023:0&gt; :simba.to_s.object_id=&gt; 260irb(main):024:0&gt; :simba.to_s.object_id=&gt; 280</code></pre><p>Creating a new object for every <code>symbol</code> to a <code>string</code> conversionallocates new memory which increases overhead.The light was thrown on this issue by<a href="https://bugs.ruby-lang.org/users/6346">schneems (Richard Schneeman)</a>in a talk at RubyConf Thailandwhere he showed how <code>Symbol#to_s</code> allocationcauses significant overhead in <code>ActiveRecord</code>.This inspired <code>Ruby</code> communityto have a new method <code>name</code> on <code>Symbol</code>which returns a <code>frozen string</code> object.This reduces the string allocations dramaticallywhich results in reducing overhead.</p><pre><code class="language-ruby">irb(main):001:0&gt; :simba.name.frozen?=&gt; trueirb(main):002:0&gt; :simba.name.object_id=&gt; 200irb(main):003:0&gt; :simba.name.object_id=&gt; 200</code></pre><p>The reasonto bring this feature wasthat most of the timeswe want a simple string representationfor displaying purposeorto interpolate into another string.The result of <code>to_s</code> is rarely mutated directly.By introducing this methodwe save a lot of objectswhich helps in optimization.Now we know the benefits of <code>name</code>,we should prefer using <code>name</code> over <code>to_s</code>when we don't want to mutate a string.</p><p>For more information on discussion,official documentation,please head on to <a href="https://bugs.ruby-lang.org/issues/16150">Feature #16150</a> discussion,<a href="https://github.com/ruby/ruby/pull/3514">Pull request</a>and<a href="https://www.ruby-lang.org/en/news/2020/09/25/ruby-3-0-0-preview1-released/">Ruby 3.0 official release preview</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Ruby 3 adds endless method definition]]></title>
       <author><name>Akhil Gautam</name></author>
      <link href="https://www.bigbinary.com/blog/ruby-3-adds-endless-method-definition"/>
      <updated>2020-09-15T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/ruby-3-adds-endless-method-definition</id>
      <content type="html"><![CDATA[<p>Ruby 3.0adds endless method definition.It enablesus to createmethod definitionswithout theneed of <code>end</code> keyword.It is marked as an experimental feature.</p><pre><code class="language-ruby"># endless method definition&gt;&gt; def raise_to_power(number, power) = number ** power&gt;&gt; raise_to_power(2, 5)=&gt; 32</code></pre><p>The discussion aroundit can be found <a href="https://bugs.ruby-lang.org/issues/16746">here</a>.Check out the<a href="https://github.com/ruby/ruby/pull/2996/files">pull request</a>for more details on this.</p>]]></content>
    </entry>
     </feed>