Conditional Statements

A conditional statement tests whether a statement is true or false and performs logic based on the answer. Both true and false are pseudovariables—you can't assign values to them. The former is an object of TrueClass, and the latter is an object of FalseClass.

These statements begin with if and close with end:

if x == y then puts "x equals y" end

if x != y: puts "x is not equal to y" end

if x > y
  puts "x is greater than y"
end

The separator then (or its synonym :) is optional unless the statement is on one line.

An unless statement is a negated form of the if statement. This example of unless:

unless lang == "de"
  dog = "dog"
else
  dog = "Hund"
end

is a negated form of this if statement (both accomplish the same thing):

if lang == "de"
  dog = "Hund"
else
  dog = "dog"
end

This example is saying, in effect, that unless the value of lang is de, dog will be assigned the value of dog; otherwise, assign dog the value Hund.

A while loop executes the code it contains as long as its conditional statement remains true:

i = 0
breeds = [ "quarter", "arabian", "appalosa", "paint" ]
puts breeds.size # => 4
temp = []

while i < breeds.size do
  temp << breeds[i].capitalize
  i +=1
end

temp.sort! # => ["Appalosa", "Arabian", "Paint",
"Quarter"]
breeds.replace( temp )
p breeds # => ["Appalosa", "Arabian", "Paint", "Quarter"]

The do keyword is optional:

Another form of while you can use is with begin and end, where the code in the loop is evaluated before the conditional is checked (like do/while in C):

temp = 98.3

begin
  print "Your temperature is " + temp.to_s + " Fahrenheit. "
  puts "I think you're okay."
  temp += 0.1
end while temp < 98.6

puts "Your temperature is " + temp.to_s + " Fahrenheit."

You can break out of a while loop with the keyword break:

while i < breeds.size
  temp << breeds[i].capitalize
  break if temp[i] == "Arabian"
  i +=1
end
p temp # => ["Quarter", "Arabian"]

When the if modifier following break found Arabian in the temp array, it broke out of the loop right then.

As unless is a negated form of if, until is a negated form of while. Compare the following statements:

weight = 150
while weight < 200 do
  puts "Weight: " + weight.to_s
  weight += 5
end

Here is the same logic expressed with until:

weight = 150
until weight == 200 do
  puts "Weight: " + weight.to_s
  weight += 5
end

And as with while, you have another form you can use with until, that is, with begin/end:

weight = 150

begin
  puts "Weight: " + weight.to_s
  weight += 5
end until weight == 200

In this form, the statements in the loop are evaluated once before the conditional is checked.

Ruby's case statement together with when provides a way to express conditional logic in a succinct way. It is similar to the switch statement found in other languages, but case can check objects of any type that can respond to the equality property and/or any equivalence operators, including strings. Using case/when is more convenient and concise than if/elsif/else because the logic of == is assumed. Examples follow:

lang = "fr"
dog = case lang
  when "en": "dog"
  when "es": "perro"
  when "fr": "chien"
  when "de": "Hund"
  else       "dog"
end

The string chien is assigned to the variable dog because the value of lang is the symbol fr. If the lang variable held a symbol instead of a string, the code would look like:

lang = :de

dog = case lang
  when :en: "dog"
  when :es: "perro"
  when :fr: "chien"
  when :de: "Hund"
  else      "dog"
end

The string value Hund is assigned to dog because the value of lang is :de. The next example uses several ranges to test values.

scale = 8
case scale
  when    0: puts "lowest"
  when 1..3: puts "medium-low"
  when 4..5: puts "medium"
  when 6..7: puts "medium-high"
  when 8..9: puts "high"
  when   10: puts "highest"
  else       puts "off scale"
end

The printed response will be high because scale is in the range 8 to 9, inclusive.

This example of a for loop uses a range (1..10) to print out a list of numbers from 1 to 10, inclusive. The do is optional, unless the for loop is on one line:

for i in 1..10 do print i, " " end # => 1 2 3 4 5 6 7 8 9 10

for i in 1..10
  print i, " "
end
# => 1 2 3 4 5 6 7 8 9 10

This for loop prints out a times table (from 1 to 12) for the number 2:

for i in 1..12
  print "2 x " + i.to_s + " = ", i * 2, "\n"
end

This is a nested for loop that you can use to print times tables from 1 times to 12 times:

for i in 1..12
  for j in 1..12
    print i.to_s + " x " + j.to_s + " = ", j * i, "\n"
  end
end

An alternative to the for loop is the times method (from class Integer):

12.times { |i| print i, " " } # => 0 1 2 3 4 5 6 7 8 9 10 11

The ternary or base three operator (?:) is a concise structure that descended from C to Ruby. It is also called the conditional expression. An example follows:

label = length == 1 ? " argument" : " arguments"

This expression assigns a string value to label based on the value of length. If the value of length is 1, the string value argument (singular) will be assigned to label; but if it is not true—that is, length has a value other than 1—the string value of label will be arguments (plural).

The following structures allow code to execute before and after a program runs. Both BEGIN and END are followed by blocks enclosed by braces ({}):

BEGIN { puts "Date and time: " + Time.now.to_s }

def bmi( weight, height )
  703.0*( weight.to_f/(height.to_f**2))
end

my_bmi = bmi( 196, 73 )

puts "Your BMI is: " + x = sprintf( "%0.2f", my_bmi )

END { puts "You've got some work ahead of you." }