Ruby: If Statements

One of the most powerful features present in most programming and scripting languages is the ability to change the flow of the program as certain conditions change. The simplest form of flow control and logic in Ruby is called an "if statement" (or technically speaking in Ruby, since everything is an expression, an "if expression").

These 'if' experssions essentially check whether a condition is true or not. In Ruby they are created by writing the if keyword, followed by a condition, optionally followed by the then keyword, then the code you want to execute if the condition is true, and then finally the end keyword to end the structure. So they should look something like the following:

1
2
3
if condition then
	#Code to execute if 'condition' is true
end

As mentioned though, the then is often dropped from the structure as it simply provides separation from the condition and the code to execute - one-line 'if' statements require the then to separate these, but multi-line ones like we'll be writing most of the time can use a new line to separate the condition and code.

1
2
3
if condition
	#Code to execute if 'condition' is true
end

From here the obvious question is: "How do I formulate a condition?". Well firstly, it's important to note that any expression that evaluates to a 'true' or 'false' value can be in the place of the condition there -- that includes boolean variables and method calls! So the following would always output "Hello" as 'some_variable' will, in this case, always evaluate to true:

1
2
3
4
5
some_variable = true

if some_variable #In this case, 'if true' would do exactly the same!
	puts "Hello"
end

"Real" conditions, for example comparing one variable to another, can be created by using 'conditional' or 'comparison' operators. These are operators that are made for comparing things, and when values are present at both sides of the operator, this will result in a 'true' or 'false' value. The basic conditional operators are:

  • == - Is equal to
  • != - Is not equal to
  • > - Is greater than
  • < - Is less than
  • >= - Is greater than or equal to
  • <= - Is less than or equal to

So to put these into actions, let's create a basic script which checks if the user is an administrator of our made-up system – it's not going to be very secure or really good for anything at the moment, but it'll be a good example to make sure we know this stuff.

The easiest way to authenticate a user is probably via a username and password, so the first thing our example script should do is ask for this data. Luckily we already know how to do this using puts and gets, however in this example it's more suitable to use print instead of puts - the two essentially do the same thing, however puts appends a newline to the output whereas print does not. So let's write this portion of the script!

1
2
3
4
print "Username: "
username = gets.chomp
print "Password: "
password = gets.chomp

From here, the 'if' statements need to do their magic. In this case we can just hard-code the administrator username and password into our script (not a good idea in a real system, but it'll work fine here). So first our comparison between the administrator username and what the user actually entered:

1
2
3
if username == "foo" #"foo" in this case is our administrator username
	#Stuff to do if username is correct
end

From here we want to check if the password is correct. If statements and other similar structures can actually be nested, so in this case it might be a nice idea to put another 'if' statement inside this one to check if the password is correct, like so:

1
2
3
4
5
if username == "foo" #"foo" in this case is our administrator username
	if password == "bar" #"bar" in this case is our administrator password
		puts "Welcome, administrator!"
	end
end

You can see I've added a little puts message so that we can tell when the username and password were correct ("foo" and "bar"). If you take our code so far and put it into a ruby file and run it, you should see that our special message only displays when "foo" and "bar" are entered! But what do we do if we want something to happen when the username and password are entered wrongly? Perhaps we want to display a message telling the user that the details they entered were wrong. We could write a few 'if' statements that use the "is not equal to" (!=) operator, however this seems like a waste of processing power given that we've already determined if the credentials are correct or not. This is where 'else' statements come in.

After an 'if' statement, just before 'end', you can introduce an 'else' clause. The code in this clause will execute if the 'if' statement was not true (and if none of the other 'if's in that chain were true, but we'll get on to this in a minute). These are accomplished using the else keyword where end would usually be, and moving end to the end. The syntax is as follows:

1
2
3
4
5
if condition
	#Stuff if condition is true
else
	#Stuff if condition is false
end

In our example we could easily utilise this functionality to output errors to the user in our example program:

1
2
3
4
5
6
7
8
9
if username == "foo" #"foo" in this case is our administrator username
	if password == "bar" #"bar" in this case is our administrator password
		puts "Welcome, administrator!"
	else #If the user's password is not "bar"
		puts "Incorrect password."
	end
else #If the user's username is not "foo"
	puts "Incorrect username."
end

As I previously touched on however, you can actually have more than one condition in an 'if' statement "chain", in which case the 'else' clause will only happen if none of the conditions are true. A nice way to show this in our example is if our system had multiple users. Perhaps we want to add a 'guest' user which doesn't require a password. We can add these "extra conditions" by using what is called an 'else if', written via the elsif keyword. Reading 'if' chains out-loud often makes some sense of them: "If this, do this, else if this, do this, else if this, do this, else, do this", this should also make obvious the fact that the next item in the chain will only be proceeded to if the previous is false – so elsifs are only checked if the primary condition is false, and elses are only checked if everything else is false. The syntax of an 'elsif' in a chain is as follows:

1
2
3
4
5
6
7
if condition
	#Stuff if condition is true
elsif condition2
	#Stuff if condition2 is true but condition1 is false
else
	#Stuff if condition and condition2 are false
end

With this, it should be fairly easy to create a guest user:

1
2
3
4
5
6
7
8
9
10
11
if username == "foo" #If it's the administrator
	if password == "bar" #If the password is correct
		puts "Welcome, administrator!"
	else #If the password is not  correct
		puts "Incorrect password."
	end
elsif username == "guest" #If it's the guest user
	puts "Welcome, guest!"
else #If no known username was entered
	puts "Incorrect username."
end

You could argue that asking the 'guest' user for their password isn't necessary, and this could be fixed by moving the password prompt and gets into the administrator 'if' statement, and feel free to see if you can do this, however it's not important for this example.

The best way to learn about 'if' statements is really to play around with them. A good idea might be to try creating a script which takes the score for an exam out of 100 and then outputs a grade depending on the score entered (within certain grade boundaries – the greater than and less than comparisons should be useful here!). The only problem you might run into in creating this script is the comparison of different data types. If you try to compare a string variable (for example something received from gets) with an integer (like 1), then you will run into problems. As such, you might want to explore to to_i and to_s methods. The former will likely want to be used in this example and is a method to convert strings to integers, while the latter is less useful in this example however may be more useful in others, and converts integers to strings.

You could use the to_i method on the gets.chomp itself (probably the better option here), or if you wanted you could use it in every condition with comparison to an integer. The former is shown, basically, below:

1
2
3
4
5
6
print "Enter a score: "
score = gets.chomp.to_i

if score > 9000
	puts "It's over 9000!"
end

Moving away from this a bit, which hopefully you should now understand and be able to use, there is also some more flexibility and some more shorthand options in this 'if' functionality. Firstly, a basic 'if' can actually be after the line that should be executed if it's true, like so:

1
puts "5 is greater than 4!" if 5 > 4

Similarly, a basic 'if' statement can be compressed to one line if the then keyword is used to replace the newline:

1
If 5 > 4 then puts "5 is greater than 4!" end

Ruby also has something called a "ternary operator" which provides a shortcut way of making basic comparisons. The syntax of this is a condition, followed by a question mark, followed by the expression that should be given if the condition is true, followed by a colon, followed by the expression that should be given if the condition is false, as can be seen below:

1
condition ? true_expression : false_expression

This is useful when a quick and compact decision between expressions is necessary, for example the following:

1
2
3
4
print "Username: "
username = gets.chomp

puts username == "admin" ? "Welcome, master!" : "Hi, #{username}."