stupid ruby tricks

stupid ruby tricks

Over the past few months of slinging Ruby here at Thoughtbot, I’ve picked up quite a few stupid ruby tricks smart ruby techniques that really help out your code. If you’ve got your own, feel free to leave a comment.

Destructuring yielded arrays

def touch_down
yield [3, 7]
puts "touchdown!"
end

touch_down do |(first_down, second_down)|
puts "#{first_down} yards on the run"
puts "#{second_down} yards passed"
end

=> "3 yards on the run"
=> "7 yards passed"
=> "touchdown!"

At first glance, this barely looks like valid Ruby. But somehow, it just makes sense: it splits up the array. If you’re going to pull out the values of the array inside of the block, why not just do it when you’re defining the block-level variables? This doesn’t seem to work nicely (in 1.8.7 at least) for Hashes, though.

Pulling out elements of an array

>> args = [1, 2, 3]
>> first, *rest = args

>> first
=> 1

>> rest
=> [2, 3]

I knew about splitting up arrays before into individual arguments, but I didn’t know that you could easily get an array of the rest. Perhaps this is Lisp inspired?

Hash#fetch

>> items = { :apples => 2, :oranges => 3 }
=> items = {:apples=>2, :oranges=>3}

>> items.fetch(:apples)
=> 2

>> items.fetch(:bananas) { |key| "We don't carry #{key}!"}
=> We don't carry bananas!

This is just a nice little way to provide some default behavior that might be nicer than checking if the value exists in the hash first.

Hash#new with a block

>> smash = Hash.new { |hash, key| hash[key] = "a #{key} just got SMASHED!" }
=> {}

>> smash[:plum] = "cannot smash."
=> {:plum=>"cannot smash."}

>> smash[:watermelon]
=> {:plum=>"cannot smash.", :watermelon=>"a watermelon just got SMASHED!"}

This is a really neat way to cache unknown values for Hashes (read: memoization!) I also heard it’s awesome for implementing a Fibonacci sequence.

Array#sort_by

>> cars = %w[beetle volt camry]
=> ["beetle", "volt", "camry"]

>> cars.sort_by { |car| car.size }
=> ["volt", "camry", "beetle"]

So, Array#sort_by sorts based on the return value of the block. It’s like a built in #map and #sort that rules even more with some Symbol#to_proc magic.

String#present?

>> "brain".present?
=> true

>> "".present?
=> false

I’m sure most Rails developers know about blank? from ActiveSupport, but what about present?. Yeah, it blew my mind too. I like being as positive as possible in conditionals, so toss out those !something.blank? calls today and start using this.

Nick Quaranto Developer

Sharpen your programming skills by completing coding exercises that are reviewed by other developers at Upcase today.