Flow Control#
if-then-else#
if-then-else statement in Ruby is quite similar to the other programming languages and to the Shell Script. The syntax is following:
if contitional_expression [then]
expressions ...
elsif contitional_expression [then]
expressions ...
else
expressions ...
end
Just to remind - in Ruby, conditional expression is true unless it evaluates to false
or nil
. All except false
and nil
is true. Number zero, empty array, zero-length string - all of this object means true in Ruby conditionals.
The keyword elsif
means else if - the next conditional expression which is checked when all the expressions before evaluates to false. The code after else
is running if all the coditionals evaluate to false
or nil
.
The word then
is optional and it have to be use only if you want to put the code in the same line. It is not very common, because Ruby have the better way to describe such expressions in one line - see conditional modifier below.
if []
puts 'Empty array is not nil or false!'
end
if 3>2 then
puts 'it is indeed'
end
if 3>2 then puts 'it is indeed' end # using 'then' to create one line expression
Conditional Modifier#
Conditional modifier is a very interesting and popular way to write conditional expression in the one line. The syntax is reversed - first goes the code, then the condition: statement if conditional_expression
. The statement will be executed only when conditional_expression evaluates to true. This is simpler and better readable for humans.
array.push 'foo' if not array.include? 'foo' # push string 'foo' if array does not include it
#=> ["foo"]
array.push 'foo' if not array.include? 'foo' # trying again
#=> nil
array # only one object in the array
#=> ["foo"]
Unless#
For better human readability Ruby provides the keyword unless
. It is the oposite for if
and means simply if not
. It can be used both in unless-then-else expressions (but there is no equivalent to elsif
) and conditional modifiers. Especially for this one it provides pretty code, which everyone can easy read, even without the knowledge of the language.
array.push 'foo' unless array.include? 'foo' # push string 'foo' unless array includes it
Conditional Expressions Returning Values#
In Ruby, everything returns value. That means that if-then-else does it as well - returns the value of last processed statement.
Also, we have a c-style conditional operator: condition ? true_expression : false_expression
, evaluates and returns true_expression
only if condition
evaluates to true or false_expression
if it evaluates to false
or nil
.
if a > b # procedural way to find out the maximum value of two variables
max = a
else
max = b
end
max = if a > b # functional-style way to do the same
a
else
b
end
# one-liner in this case doesn't look so bad:
max = if a > b then a else b end
# c-style conditional expression:
max = a > b ? a : b
Case Statement#
Case statement in Ruby is similar to case/esac in Unix Shell. It evaluates the expression and, depends on the value, runs the specific code parts. The syntax:
case expression
when value then statement # for one-liners use 'then'
when value, value # if any of this values fits
statements
else # in case no values fits the expression
statements
end
Identical to if-then-else, case
expression returns value . The example below shows both ways to use case
statement in Ruby:
case netmask # netmask is a string with network mask
when '255.0.0.0'
address_class = 'A' # this is Class A subnet
when '255.255.0.0'
address_class = 'B'
when '255.255.255.0'
address_class = 'C'
else
puts "[ERROR] unknown Netmask #netmask"
address_class = nil # nil in this case means 'unknown class'
end
address_class = case netmask
when '255.0.0.0' then 'A'
when '255.255.0.0' then 'B'
when '255.255.255.0' then 'C'
else
puts "[ERROR] unknown Netmask #netmask"
nil # this is unnecessary, because puts returns 'nil'; done for better readability
end
Case Equality Operator in Case Statement#
When discussing ranges and type system we mentioned about case equality (triple equal sign) operator. In most cases, this operator is identical to normal equality (==
) - so, for example, 1 === 1.0
is true. But in some cases it is a kind of extention. For example in Range
you can check if the object is within the specific range: (1..100) === 3.14
, or you can check if the object is kind of the class: Integer === 42
. In case statement, the expression after keyword ‘case’ is compared with the values (coming after ‘when’) using this operator (so that is why it is called the ‘case equality operator’). In the example below we assume that http_return_code
variable contains some return code from http request (like 404 - not found):
case http_return_code
when 100..199
puts "Informational"
when 200..299
puts "Successfull"
when 300..399
puts "Redirection"
when 404 # if return code is 404, it will match here
puts "*** Page not found" # and finish the case statement
when 400..499 # so in this case
puts "Client Error" # this code will not be evaluated
when 500..599
puts "Server Error"
else
puts "*** Unknown"
end
Case statement is often used to determine the object type in functions which can have object of many types as the argument. The good example is the []
method for selecting substrings from string: it can take an integer (s[3]
) and then return the single character, the range (s[1..3]
) and return the substring, or you can use Regular Expression or even String as an argument. The other example is to pass an object or array of objects as the argument, and when the argument is array, process with all elements.
case argument
when NilClass
puts "Server can't be nil!"
when WindowsServer
puts "Can't ssh to Windows, delete everything manually"
when UnixServer, MacOSXServer
argument.ssh "root", "root123", "rm -rf /" # this classes should have defined 'ssh' method
when Array
# below is the ruby way to do the loop, see next chapter
for machine in argument
machine.ssh "root", "root123", "rm -rf /"
end
end