Don’t iterate to convert built-in Ruby data types

Both the Ruby language and the Ruby on Rails framework provide a lot of convenience methods compared to other technology stacks, improving ease of use and developer productivity. However, it’s difficult when starting out with Ruby to know what ease-of-use functions are available to you as a programmer.

Here’s a heuristic to help with that: if you’re writing a Ruby program, and you find yourself writing code that uses iteration to convert one built-in data type to another, there’s probably a language feature that could simplify your code. Let’s go through a few examples of this that I’ve encountered since I started coding in Ruby.

Generating an array of numbers between 1 and N

Suppose you want to generate an ordered array of integers between 1 and N. We might be tempted to use the .times method on our integer N, convert that enumerator to an array, then map each number to be increased by 1 (since .times provides us numbers from 0 to N – 1). For example, if N is 5, we can use the following code:

5.times.to_a.map{|n| n + 1}
=> [1, 2, 3, 4, 5] 

This works, but Ruby provides simpler ways for us to achieve the same goal using upto or a Range:

1.upto(5).to_a
 => [1, 2, 3, 4, 5] 

(1..5).to_a
 => [1, 2, 3, 4, 5] 

Convert the values of a hash into an array

Suppose you want an array containing the values of a Hash, and don’t need to know what the keys are. We might be tempted to call .map on the Hash, and then return the value in that block:

{foo: 1, bar: 2, car: 3}.map{ |_key, value| value }
 => [1, 2, 3] 

With far fewer keystrokes, .values lets us do the same thing:

{foo: 1, bar: 2, car: 3}.values
 => [1, 2, 3] 

(Of course, if we’re interested in the keys and not the values, Ruby provides a .keys method as well.)

Combining two hashes

Suppose have two Hash variables, h0 and h1, and want to create a new Hash containing the keys and values in both of them. In the case of duplicate keys between h0 and h1, we’ll take the value from h1 (this is arbitrary; using the value from h0 would be valid too). We could write a method to iterate over two hashes like so:

However, the far simpler approach is to use the .merge method provided by Ruby:

{foo: 1, bar: 2}.merge({bar: 3, car: 4})
 => {:foo=>1, :bar=>3, :car=>4} 

Conclusion

Ruby (and Ruby on Rails) provides us with a lot more convenience methods than other popular languages like Go and JavaScript. Learning all of them requires reading the language documentation, along with simply practicing with the language over time. However, these convenience methods aren’t created at random; there are patterns in them that we can identify to become more effective Ruby developers.

Start your journey towards writing better software, and watch this space for new content.