Share

This is a continuation of the following series of posts
Quick Ruby Tutorials-1
Quick Ruby Tutorials-2
Quick Ruby Tutorials-3

Currently our Dog eats, anything and everything given to it. Lets give our dog some choice.
if you give the dog chocolate, it should ask for some more, otherwise it should behave normally.

class Dog

 def eat(food="bone")
  puts "I am eating #{food}"
  if (food == "chocoloate") # parnthesis are optional
   puts "Give me some more"
  end
 end
end

d = Dog.new
d.eat("bread") # I am eating bread
d.eat("chocolate")
#I am eating chocolate
#Give me some more.

In the above code, we are using the If statement to make decisions ie to execute a certain part of code only if a particular condition is satisfied.

Syntax of if statement is as follows

if (<expression1>)
 # code1 which executes when expression1 is true
elsif (<expression2>)
 # code2 which executes when expression2 is true and expression1 is false
elsif (<expression3>)
 # code3 which executes when expression3 is true and expression 1 & 2 are false
else
  #code 4 which executes when expression 1&2&3 are false.
end

The expression can be any ruby statement. If the output of the expression is true/not nil then the corresponding code is executed other wise it moves to the next elsif/else

So above
if expression1 one evaluates to true then code 1 is executed
if expression1 is false and expression2 is true then code2 is executed

if no expression is evaluated to true then the code in the else block is executed.

The elsif and the else block are optional.
There can be multiple elsif blocks but only one else block.
Else block does not accept any argument.
The else block is the last block in the if statment. After that there can be no further elsif/else
The if statement ends with a “end” irrespective of then number of elsif.

There can be different forms of if statements given below

if(expression)
 #code which is executed if expression is true
end

A short form for this is this is

code if expression

This is called a one liner if statement
Example:

speed  = 80
puts "Drive Slow" if speed > 60 # Drive Slow

time = "afternoon"
puts "Good Morning" if  time == "morning" #

The one liner if statements are very useful when there is no elsif/else part and the body of the if is just a single line of ruby code.

if expression
 #code1
else
 #code2
end

Here one of the parts code1 or code2 is always executed.

if expressoin1
 #code1
elsif expression2
 #code2
end

Here if expression1 is true then code1 is executed, if expression1 is false but expression2 is true then code2 is executed. If both are false then nothing is executed.

More about expressions.
Again: The body of the if statement is executed if the expression evaluates to true or a non nil value which is not false.
Or
The body of the if statement is not executed if the expression evaluates to false or nil.
We will demonstrated this using one liner if statement.
In the body of the one liner if, we will keep a puts statement.
So if there is any output on screen, then we know that the expression has been satisfied.

 puts "3 is greater than 2" if 3 > 2 #3 is greater than 2
 puts "this will not print" if 2 > 3 #
 puts "2 is less than 3" if 2 < 3 # 2 is less than 3
 puts "this will not print" if 3 < 2 #
 puts "3 which is a non nil object evaluates to true" if 3 #3 which is a non nil object evaluates to true
 puts "true" if true # true
 puts "this will not print" if false #
 puts "this will not print" if nil
 puts "3 is equal to 3" if 3 == 3 # 3 is equal to 3
 puts "x is equal to 3" if x = 3 # x is equal to 3
 puts "3 is not equal to 2" if 3 != 2 #3 is not equal to 2

Above we have used constants in the expression. This was to keep things simple.
We can use variables, method calls, and their combination in an expression.
Every expression can be a combination of objects, methods calls, operators.

2 important things to note from the above example are:

we can check whether an variable/object x exists by doing

if x

The if statement is only executed when the object x exists ie when its value is not nil.

Second thing is, in case of an assignment operation, the output of the expression is the value which is assigned.
So if we do
x = y
then the output of this expression is y.

Coming back to the dog example:
Lets modify our Dog class so that,
if you give it “banana” to eat, the dog should not eat. It should ask for something else.

class Dog

 def eat(food="bone")
  if food == "banana"
   puts "I do not eat banana, give me something else"
  else
   puts "I am eating #{food}"
  end

  if food == "chocolate"
   puts "Give me some more"
  end
 end
end

d = Dog.new
d.eat("banana") #I do not eat banana, give me something else
d.eat("bread") # I am eating bread
d.eat("chocolate")
#I am eating chocolate
#Give me some more.

Note that the condition if food == chocolate is being tested for even if the food is banana. We should move that loop into the body of if. This is called nested if ie an if inside if.

class Dog
 def eat(food="bone")
  if food == "banana"
   puts "I do not eat banana, give me something else"
  else
   puts "I am eating #{food}"
   if food == "chocolate"
    puts "Give me some more"
   end
  end
 end
end

d = Dog.new

d.eat("banana") #I do not eat banana, give me something else
d.eat("bread") # I am eating bread
d.eat("chocolate")
#I am eating chocolate
#Give me some more.

It would much cleaner if we add a one liner if condition here, that makes it much more readable

class Dog
 def eat(food="bone")
  if food == "banana"
   puts "I do not eat banana, give me something else"
  else
   puts "I am eating #{food}"
   puts "Give me some more"   if food == "chocolate"
  end
 end
end

Lets add some more conditions, If you give it bone then it should say “great, u made my day”.
if you give it “sandwich” then it should say “mmmmmmmmmmmm, I have never eaten like this one before”
if you give it milk, then it should tell “Thankyou, I will become a strong dog after drinking milk”
Previous conditions also apply. It should not say “I am eating xyz” along with other statements as above.

class Dog
 def eat(food="bone")
  if food == "banana"
   puts "I do not eat banana, give me something else"
  elsif food ==  "chocoloate"
   puts "Give me some more"
  elsif food == "bone"
   puts "Great, you made my day"
  elsif food == "sandwich"
   puts "mmmmmmmmm  I have never eaten like this one before"
  elsif food == "milk"
   puts "Thank you, I will become a strong dog after drinking milk"
  else
   puts "I am eating #{food}"
  end
 end
end

We replace this by a case statement.
Case statement is an alternative for a if statement.
If the output of a calculation depends on a value of an object, and the number of cases are high then it can become very cumbersome if you use if statement. It is much easier doing the same using a case statement.
Syntax for the case statement is :

case value
   when match_1 then result_1
   when match_2 then result_2
   when match_3 then result_3
   when match_4 then result_4
   else result_5
end
</end>

<code lang="ruby">
class Dog
 def eat(food="bone")
   message = case food
   when "banana" then "I do not eat banana, give me something"
   when "chocolate" then "Give me some more"
   when "bone" then  "Great, you made my day"
   when "sandwich" then "mmmmmmmmm  I have never eaten like this one before"
   when "milk" then  "Thank you, I will become a strong dog after drinking milk"
   else  "I am eating #{food}"
  end
  puts message
 end
end

So this looks much cleaner the the code with if statement.

Note how we collected the output of the case statement in the variable message, and then printed the variable. We could have instead printed the value in the case statement it self as done in the if statement.
But this one is better, as if later, instead of printing the message on screen, I just want to return the message, or store it in a file then I would need to just change one line. Instead if we had embedded the puts in the case itself, then we would need to change many lines.
The code which adapts to a change, with lesser lines of changes, in lesser number of files, is a better code.

Let us take a different scenario:
A dog will reject the following items: banana, mango
It will accept the following : biscuit, bread, milk

class Dog
 def eat(food="bone")
  if food == "banana" || food == "mango"
   puts "I do not eat #{food}, give me something else"
  elsif  food == "milk" || food == "bread" || food == "biscuit"
   puts "thank you for giving me #{food}"
  else
   puts "Can this be eaten?"
  end
 end
end

d = Dog.new

d.eat("banana") #I do not eat banana, give me something else.
d.eat("bread") # thank you for giving me bread.
d.eat("ball") # can this be eaten?

Now,if this list of eatables gets very long( the food which dog can eat and once which it cannot), then the program would become very cumbersome.
Let us use some magic of arrays to this.

class Dog

 @@good_food = ["milk", "bread", "biscuit","bone"]
 @@bad_food = ["banana", "mango"]

 def eat(food="bone")
  if @@bad_food.include? food
   puts "I do not eat #{food}, give me something else"
  elsif @@good_food.include? food
   puts "thank you for giving me #{food}"
  else
   puts "Can this be eaten?"
  end
 end

end

Here we are defining 2 class variables: @@good_food and @@bad_food. We initialize each of these to an array holding the respective food types.

In the if statement we use a method include?(x) on the array object.
This method returns true if x is present in the array else it returns false.
For a complete list of methods present in the array classs go to: http://ruby-doc.org/core/classes/Array.html

One fine day our dogs realize that global warming is increasing a high rate.
All the scientist dogs get together and do a research on this. They come to a conclusion that the major cause of the global warming is non vegetarianism(http://www.goveg.com/environment.asp).
So they all decide to go veg
Now if you gave our veg dogs a bone or meat to eat, should reject it, telling that stop non veg,stop global warming!.
Let us modify our code to do the same.

class Dog
 @@non_veg_food = ["bone","meat"]
 @@good_food = ["milk", "bread", "biscuit"]
 @@bad_food = ["banana", "mango"]

 def eat(food="bone")
  if @@bad_food.include? food
   puts "I do not eat #{food}, give me something else"
  elsif @@good_food.include? food
   puts "thank you for giving me #{food}"
  elsif @@non_veg_food.include? food
   puts "Go Veg, Stop Global Warming!"  
  else
   puts "Can this be eaten?"
  end
 end
end

dog = Dog.new
dog.eat("bone") #Go Veg, Stop Global Warming!

So, by now our dogs have become very choosy. You can go ahead and do the following extensions:

  • Add methods to the class to modify(add/remove) the food choices of the dog
  • Currently all our dogs have the same choices, add functionality so that each dog can have their own choices, they may have some default choices when the are born.
  • Let the food habits of a dog develop automatically: When a dog is given a food to eat when it is hungry, add the foo to the good food list, when a dog is given food to eat when it is not well, or when it is not hungry then add the food to bad food list.

These are just ideas, you can try whatever comes to your mind, be creative :) .

Share

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.