Ruby If, Unless, While and Until

Ruby If, Unless, While and Until

A step by step tutorial on the ruby if, unless, while and until control structures.

Ruby offers conventional control structures that are found in most common programming languages like if, else and while, however, Ruby also provides less common options like until and unless. These control structures may seem weird at first (“who talks like that?”), but they have their advantages.

If Statement

Let’s start with a basic if statement. Here we have a Movie class with several attributes and functionality to only update a movie’s title if the in_progress attribute is true; easy enough. If in_progress is true, then the title attribute can be assigned a new value.

class Movie
  attr_accessor :in_progress
  attr_reader :title, :length, :budget

  def title=(new_title)
    if @in_progress
      @title = new_title
    end
  end
end

Now let’s imagine if the attribute was finalized instead of in_progress. It may be tempting to put a not or ! in front of it and call it a day.

class Movie
  attr_accessor :finalized
  attr_reader :title, :length, :budget

  def title=(new_title)
    if not @finalized
      @title = new_title
    end
  end
end

This if statement is valid but is a little more verbose than it has to be. An alternative (and slightly more concise) way would be to use unless.

class Movie
  attr_accessor :finalized
  attr_reader :title, :length, :budget

  def title=(new_title)
    unless @finalized
      @title = new_title
    end
  end
end

Using unless, the body of the statement (@title = new_title) is only executed if the condition (@finalized) is false. Using unless comes with a couple of benefits:

  1. It’s slightly shorter that using if not or if !
  2. It may become a little easier to read and understand once you get used to it

The second point is important. Reading an unless statement may seem weird at first (when I first encountered it in a production app I had to read it as “if not” until I got used to it). But after a while it becomes less awkward and just another way to do a negative, or backwards, if statement.

There’s no “right” way to do it; it’s just a preference. The difference between an if not and unless is like saying:

  1. “It is not true that an apple is an orange”
  2. “An apple is not an orange”

While and Until

Similar to unless is the negative version of if, until is the negative version of while

A while loop will keep looping while the condition (! download.is_finished?) is true. In this example, the condition reads “while not download is finished (execute the code block)”.

while !download.is_finished?
  spinner.keep_spinning
end

An until loop will keep looping until the condition (download.is_finished?) is true. In this example, the condition reads “until download is finished (execute the code block)”.

until download.is_finished?
  spinner.keep_spinning
end

Again, it’s a matter of preference; but using until became clearer once I understood the difference and became used to it.

We can also make these examples a little more concise and readable. Notice how the code block of the statements are only one line? Because it’s only one one line and is pretty short, we can condense the statements to just a single line.

spinner.keep_spinning while !download.is_finished?
spinner.keep_spinning until download.is_finished?

Just as before, it’s a matter of preference, but to me using until is clearer and reads a little better.

That’s part of the reason I really like writing code in Ruby, there are multiple ways to do the same thing. The language provides tools you need to express yourself and does its best to stay out of your way. Does not if make more sense to you or does writing unless statements feel more natural? Either way is fine because Ruby provides both options! Same thing with while and unless.