Ruby Idioms, Part 1

January 22, 2007

With more people moving to Ruby everyday from languages like Java, I wanted to create blog entries on the most common Ruby idioms (especially ones frequently found in Rails core or Rails application code) and briefly explain how to convert your Java mindset to Ruby (over time).

This is the first installment.

First let us inspect what we might do in Java (converted to Ruby syntax) when determining if a value passed in equals various fixed values:

    if val == 1 || val == 3 || val == 5
      puts "hello odd number under 7"
    end

Rubyists will know this is really ugly, so our first attempt at Rubifying the code above would probably look like:

    if [1, 3, 5].include? val
      puts "hello odd number under 7"
    end

Of course, one-liner fans should note you can also do the following:

    puts "hello odd number under 7" if [1, 3, 5].include? val

include? is an instance method on Array (a builtin Ruby class - remember all first class citizens in Ruby are classes [or more technically, modules]). In Ruby developers use "?" postfixes in method names as a way to letting clients of the method know it should return a true or false value. I described the unwritten/unofficial Ruby conventions and guidelines for naming in a previous blog entry, Rubyisms: Naming Conventions.

This first attempt is fairly nice, because it makes (in my opinion) the code more readable and more like my natural language, English. Now it doesn't quite read as well as it could, so let's try again:

    class Array
      alias :includes? :include?
    end

    if [1, 3, 5].includes? val
      puts "hello odd number under 7"
    end
    # OR the one-liner version
    puts "hello odd number under 7" if [1, 3, 5].includes? val

The code snippet above reopens a class in Ruby, a facility I describe in a previous blog entry Rubyisms: Reopening Classes.

Now some of you might be saying, "this is terrible…you have converted a 3 line code snippet into 6." Well not exactly. The reason is, the first three lines just need to be put in a ruby file to extend the Array class just once in the whole application, library or framework and you can use the aliased method, includes? as many times as you like throughout the code base with not a care in the world.

There are a variety of ways to change the code to be more readable and this gets subjective, but I'll leave that as an exercise for the reader. Ruby's core Range class could be used to generate an array of odd (or even) numbers under a specific number. Another blog entry will deal with this.