The Double Splat Operator

Sophie Déziel
Nov 23, 2016 · 2 min read

Today I read a nice article on Ruby tips by Anton Davydov. I learned about the double splat operator (**) usage in a method definition and shared the tip to my colleagues. We tried several things but we couldn’t find the difference between using it or not. This is what we tried in irb:

def without_splat(args, *others, hash_args)
hash_args
end

def with_splat(args, *others, **hash_args)
hash_args
end

with_splat(1, 2, 3, color: “blue”, other: “things”)
=> {:color=>”blue”, :other=>”things”}
without_splat(1, 2, 3, color: “blue”, other: “things”)
=> {:color=>”blue”, :other=>”things”}

Basically, hash_args seems to capture a hash, whether or not the double splat is used or not. This is not very useful… But look at the code bellow:

with_splat(1,2,3)
=> {}
without_splat(1,2,3)
=> 3

Ah ha! Without the splat, Ruby assigns the last value to hash_args because it’s the pattern we gave it to follow. The double splat tells Ruby that we expect a hash or named arguments and makes it optional. It acts kinda like hash_args={} in the method signature!

Now, let’s see if it’s different:

def with_default_value(args, *others, hash_args = {})
hash_args
end
SyntaxError: (irb):1: syntax error, unexpected '=', expecting ')'
def with_default_value(args, *others, hash_args = {})
^

Yes it is!! It allows you to capture an indefinite number of named arguments or a hash right after capturing an array of arguments, which was impossible before that.

Now, what can we do with it in the real world? Let’s say I want to implement my own version of the FactoryGirl gem (let’s call it FactoryBoy). I might use the double splat operator to implement the create method:

class FactoryBoy
def self.create(factory_name, *traits, **attributes)
# lots of useful stuff
end
end
FactoryBoy.create(:user, :admin, email: 'something@cool.com')

I looked at the FactoryGirl source code and it’s actually done in a very different way! But that’s another story…

Sophie Déziel

Written by

@sophiedeziel / Ruby on Rails developer @ Acquisio / trying to write relevant things / eating flying spaghetti monsters / trying to travel more