Ruby If, Unless, While and Until
Tags: ruby, beginners
Published: 2019-03-07 02:38:23

---
title: Ruby If, Unless, While and Until
canonical_url: https://anthonygharvey.com/ruby/ruby_if,_unless,_while_and_until
cover_image: https://thepracticaldev.s3.amazonaws.com/i/0yfuea9ooapv248fxiev.jpeg
published: true
description: A step by step tutorial on the ruby if, unless, while and until control structures
tags: ruby, beginner
---

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.

```ruby
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.

```ruby
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`.

```ruby
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)”.

```ruby
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)”.

```ruby
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.

```ruby
spinner.keep_spinning while !download.is_finished?
```

```ruby
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`.

_This article was originally published on <a href= 'https://anthonygharvey.com/ruby/ruby_if,_unless,_while_and_until' target='_blank'>anthonygharvey.com</a> on March 5th, 2019._