DEV Community

Mel Kaulfuss
Mel Kaulfuss

Posted on

Accidentally Destructuring in Ruby

The funniest thing happened to me yesterday. Funny now I guess. At the time it was distinctly unfunny. I struggled for hours on the simplest unit spec that was failing.

The response I was expecting to see in my test:

   "amount"=>{"currency"=>"AUD", "value"=>1000}
 :header=>{ "Sandwich"=>"Eggplant-Parma-Sanga"},
Enter fullscreen mode Exit fullscreen mode

The failure message, less than helpful:

  no implicit conversion of Symbol into Integer
Enter fullscreen mode Exit fullscreen mode

Staring at the code.
Staring at the spec.
Thinking I'd done something stupid in my before block.

A binding.pry in my code shows me the Hash I'm expecting to be able to access with a :response key is coming back inside an Array?!

[{:response=>{"pspReference"=>"883598242852329J", "resultCode"=>"Authorised", "amount"=>{"currency"=>"AUD", "value"=>1000}},
  :status=>200}, api_version]
Enter fullscreen mode Exit fullscreen mode

You wot m8!

It took a second pair of eyes to help spot the error.

def initialize(result:, api_version:)
  @result = result,    # <-------- this stray comma
  @api_version = api_version
Enter fullscreen mode Exit fullscreen mode

As soon as that silly stray comma was pointed out I laughed out loud.

I was accidentally Destructuring in Ruby and I'm chalking up the fact I knew that's what was happening as my win here! And also that I'd been meaning to write about Destructuring in Ruby earlier, so, win win I guess 🤷‍♀️

Destructuring is described in Common Lisp the Language, 2nd Edition as the ability to "bind a set of variables to a corresponding set of values anywhere that you can normally bind a value to a single variable".

In Ruby we assign values to a single variable like this

my_choice_sandwich = "eggplant parma"

# irb(main):001:0> my_choice_sandwich
# => "eggplant parma"
Enter fullscreen mode Exit fullscreen mode

Destructuring allows us to do multiple assignments with a simple comma separating the multiple values like so

my_choice_sandwich = "crumbed eggplant", "sugo sauce", "mozzerella"

# irb(main):001:0> my_choice_sandwich
# => ["crumbed eggplant", "sugo sauce", "mozzerella"]
Enter fullscreen mode Exit fullscreen mode

Above we see the Object on the left (the "variable") is an Array because we are passing in multiple values on the right.

You can set multiple variables (on the right) with corresponding values (on the left).

sandwich, pizzas = "salad", {vege: "mushrooms", meat: "aussie"}

# irb(main):001:0> sandwich
# => "salad"

# irb(main):001:0> pizzas
# => {:vege=>"mushrooms", :meat=>"aussie"}
Enter fullscreen mode Exit fullscreen mode

Above you'll see:
sandwich returns a String because only one value is being assigned on the right.

pizzas returns a Hash as that was the corresponding value on the right.

Isn't learning fun!

Top comments (0)