Ruby double splat (**) operator cheatsheet


The operator ** is useful as an options hash.


def one_method(**options);end

This form is completely similar to the following:


def another_method(options = {});end

In addition, you can strictly define the set of required keys for the method.


def one_strict_method(first_name:, last_name: , **options)

  puts "options: #{options}"

  greeting = "Hello #{first_name} #{last_name}"

  puts options[:upcase] ? greeting.upcase : greeting

end


pry(main)> one_strict_method(upcase: true)

ArgumentError: missing keywords: first_name, last_name



pry(main)> one_strict_method(first_name: 'John', last_name: 'Doe', upcase: true)

options: {:upcase=>true}

HELLO JOHN DOE

=> nil

Another advantage of double splat literal is that it works like #merge for Ruby Hash


class Contact::ShowRepresenter #:nodoc:

  def call(contact)

    {

      contact: {

        **base_info(contact),

        **legal_info(contact),

        # You can add something more complex here.

        # **GeoLocaionRepresenter.new.(contact)

      }

    }

  end



  private



  def base_info(contact)

    {

      id: contact.id,

      first_name: contact.first_name,

      last_name: contact.last_name,

      email: contact.email,

      phone: contact.phone

    }

  end



  def legal_info(contact)

    {

      legal_name: contact.legal_name,

      legal_type: contact.legal_type,

      mailing_address: contact.mailing_address

    }

  end

end


pry(main)>Contact::ShowRepresenter.new.(Contact.last)

=> {

  :contact=>{

    :id=>51986,

    :first_name=>"Ilia",

    :last_name=>"Kriachkov",

    :email=>"ilia.kriachkov@jetrockets.ru",

    :phone=>"+79000000000",

    :legal_name=>"JetRockets",

    :legal_type=>"LLC",

    :mailing_address=>"15 Let Oktyabrya Street, #10b, Tver, Russian Federation 170008"

  }

}

In conclusion, I want to demonstrate some benchmark results.

As you can see, the ** operator is a bit faster than Hash#merge.


require 'benchmark'

n = 50_000

Benchmark.bm(2) do |x|

  x.report('merge:             ') { n.times { merge } }

  x.report('double_splat_merge:') { n.times { double_splat_merge } }

end



def merge

  hash = { a: 'a' }

  { b: 'b' }.merge(hash)

end



def double_splat_merge

  hash = { a: 'a' }

  { b: 'b', **hash }

end


                     user      system      total        real

merge:               0.109247   0.088652   0.197899 (  0.204470)

double_splat_merge:  0.079480   0.003590   0.083070 (  0.083642)


Ilia
Kriachkov

Backend Developer at JetRockets

Explore more of JetRockets