Ruby for Newbies: Conditional Statements and Loops
basixvideos

Ruby for Newbies: Conditional Statements and Loops

Tutorial Details
  • Topic: Ruby
  • Difficulty: Easy
  • Estimated Completion Time: 30 minutes
This entry is part 4 of 13 in the Ruby for Newbies Session
« PreviousNext »

Ruby is a one of the most popular languages used on the web. We’ve started a new screencast series here on Nettuts+ that will introduce you to Ruby, as well as the great frameworks and tools that go along with Ruby development. In this chapter, we’ll be looking at how conditional statements and loops work in Ruby.


Catch Up


View Screencast

Click the HD button for a clearer picture.

Subscribe to our YouTube page to watch all of the video tutorials!


Conditional #1: If Statement

The if statement is one of the first types of branching you learn when programming. You can guess what it means: if this is true, do one thing; if it’s not, do something else. In Ruby, these are pretty easy to write:

name = "Andrew"

if name == "Andrew"
	puts "Hello Andrew"
end

if name == "Andrew"
	puts "Hello Andrew"
else
	puts "Hello someone else"
end

After the keyword if, code in your conditional statement. After that comes the code to execute if the condition returns true. You close the statement with the end keyword. If you’d like, you can squeeze an else statement in there, which will predictably execute if the condition is false.

elsif

It’s not hard to check for multiple conditions. Just put as many elsif statements as you’d like between the if and else statements. Yes, that’s elsif, a marriage of else and if.

order = { :size => "medium" }

def make_medium_cofee
	puts "making medium statement"
end

#assume other functions

if order[:size] == "small"
	make_small_coffee;
elsif order[:size] == "medium"
	make_medium_coffee;
elsif order[:size] == "large"
	make_large_coffee;
else
    make_coffee;
end

As I mentioned, you can have as many elsif conditions and their corresponding code blocks as you want.

Statements vs. Expressions

Most programming languages make a distinction between statements and expressions. A statements is a code construct that doens’t evaluate to a certain value. An expression is a code construct does return a value. For example, calling a function is an expression, because it returns a value. However, an if statement is exactly that, a statement, because it does not return a value. This means that you can’t do this in your JavaScript:

message = if (someTruthyValue) {
		"this is true";
	} else {
		"this is false";
	}

Obviously, you can’t do this because the if statement does not return a value that you can assign to message.

However, you can do this with Ruby, because statements are actually expressions, meaning they return a value. So we can do this

message = if order[:size] == "small"
        "making a small"
    elsif order[:size] == "medium"
        "making a medium"
    else
        "making coffee"
    end

Whichever block of code is executed will become the value of message.

If as a Modifier

If you don’t have any elsif or else clauses, and your if statement has only one line, you can use it as a modifier to a “normal” line.

puts "making coffee" if customer.would_like_coffee?

Conditional #2: Unless Statement

In most programming languages, we want to reverse the return of the conditional expression, we have to negate it, usually with the bang (!) operator.

engine_on = true

if !engine_on   # meaning "if not engine_on"
	puts "servicing engine"  #should not be put, because "not engine_on" is false
end

However, Ruby has a really nice unless operator, that keeps us from having to do that, while giving us much more readable code:

unless engine_on  # "unless engine_on" is better than "if not engine_on"
	"servicing engine"
end

Just like if, you can use unless as a modifier:

puts "servicing engine" unless engine_on

Conditional #3: Case / When Statement

If you’ve got a lot of options to work through, using if/elsif/else might be somewhat wordy. Try the case statement.

hour = 15

case
when hour < 12
	puts "Good Morning"
when hour > 12 && hour < 17
	puts "Good Afternoon"
else
	puts "Good Evening"
end

It’s kinda-sorta-maybe like a switch/case statement in JavaScript (or other languages), except that there’s no one variable you’re evaluating. Inside the case/end keywords, you can put as many when statements as you’d like. Follow that when by the conditional expression, and then the lines of code go after it. Just like the if statement, the case statement is really an expression, so you can assign it to an expression and capture a returned value.

hour = 15

message = case
    when hour < 12
        "Good Morning"
    when hour > 12 && hour < 17
        "Good Afternoon"
    else
        "Good Evening"
    end

puts message

Breaking Up Expressions

If you’re familiar with JavaScript, you’ll know that the blocks of code in an if statement are surrounded by curly braces. We don’t do this in Ruby, so it may seem like Ruby is dependant on the whitespace. Nothing could be further from the truth (take that, pythonistas :)).

If we want write your statements as one-liners, have to separate the different parts of the statements … but how? Well, you can use semi-colons:

if name == "Andrew"; some_code;
else; some_code; end

If you don’t like the look of that (which I don’t), you can put the keyword then between the conditional expressions and the line of code.

if name == "Andrew" then sode_code; end

This also works for a case statement.

case
    when x > 20; puts "<20"
    when x < 20 then puts "<20"
end

Loop #1: While Loop

So, those are conditional statements (I mean, expressions). How about loops? Let’s look at while loops first.

A while loop will continue to execute until the condition stated is false:

arr = ["John", "George", "Paul", "Ringo"]
i = 0

while arr[i]
    puts arr[i]
    i += 1
end

Here we’re looping over an array; when arr[i] returns false (meaning there are no items left in the array), the loop will stop executing. Inside the loop, we print out the current item in the array, and them add one to our increment variable.

You can also use while as a modifier

arr = ["John", "George", "Paul", "Ringo"]
i = -1

puts arr[i += 1] while arr[i]

Loop #2: Until Loop

Just like unless is the opposite of if, until is the opposite of while. It will continue to loop until the condition is true:

days_left = 7;

until days_left == 0
    puts "there are still #{days_left} in the week"
    days_left -= 1
end

And of course, it’s a modifier, too.

days_left = 8

puts "there are still #{days_left -= 1} in the week" until days_left == 1

Loop #3: For Loop

Yes, Ruby has a for loop. No, it’s not like the for loop in other languages. It acts like a foreach loop, for looping over the values in an array or hash:

arr = ["John", "George", "Paul", "Ringo"]

for item in arr
    puts item
end

If you’re looping over a hash, you can use two variable names, one for the key and one for the value:

joe = { :name => "Joe", :age => 30, :job => "plumber" }

for key, val in joe
    puts "#{key} is #{val}"
end

That’s it!

I hope you’re enjoying our Ruby for Newbies Screencast series. If there’s something you’d like to see, let me know in the comments! (And if you’re not watching the videos, you should be. There’s a screencast-only bonus at the end of each one.)

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://davidfitzgibbon.com David Fitzgibbon

    Great as usual! Keep em coming!

    Loving the Ruby stuff

  • http://www.devtalk.in Mohit Thakral

    Hi,

    First of all thanks for this great series. I am starting to learn ruby from here. I just have two question about this post. you haven’t explained what is this

    order = { :size => “medium” }

    I guess it is some thing like object literal in javascript.

    second thing can you please shed some more light on what is a modifier and what is their usage.

    Regards
    Mohit Thakral

    • http://andrewburgess.ca Andrew Burgess
      Author

      Thanks!

      You’re right; it’s pretty similar to an object literal in JS; it’s a hash; I went over them in Chapter 2.

      A modifier is just a conditional or loop that “modifies” a single line of code, as shown in the examples. They’re useful when your loop or condition has only one line of code inside it. Instead of adding an extra two lines for the condition/loop, just use it as a modifier. As an added bonus, it usually reads more like English.

      Let me know if that helps!

  • http://laroouse.com piyansitll

    arkadaşlar tutsplusa girip türkçe bilen kaç kişiyiz reply yapın lütfen

  • http://twitter.com/garbaczd David Garbacz

    Are this and your previous video going to be available to download for plus members? I like to keep these around in case I need to go back and take a look at something really quickly.

    Loving the series so far!

  • http://imkwaa.com Olle

    This is fantastic. Great job with the series so far. Which way is the most efficient way to print something based on a condition?

    There is obviously the obvious one, if -> puts, but I was hoping for more. In PHP I’m quite used to using short-hand coding as such: 67) ? “33% chance of this being the output”; ?>

  • http://trenthauck.com Trent

    I would love to see a Rails from Scratch like CI from Scratch, would be awesome.

  • http://www.johngadbois.com John Gadbois

    Probably because they’re not technically loops, but you didn’t mention a couple of the most widely used forms of iteration. These seem to be used much more than for or until loops

    5.times { |i| i * 2 }

    some_collection.each {
    |item| item.do_something
    }

    • http://andrewburgess.ca Andrew Burgess
      Author

      You’re right; I wanted to cover just the raw forms of loopings in this lesson. We’ll talk about iterations in a chapter or two :)

  • http://wa3l.com Wael Al-Sallami

    Good job, I recently learned ruby on rails and I even built two or three apps with it, but as I was trying to learn Rails, I guess I kinda lost my way and never actually got a firm understanding of the language itself which made me think of “ruby” as “ruby on rails”, never as a language on its own, I’m hoping I could fix that soon by reading more about the language, but you sure are helping out!.

    keep it up!

  • http://brettic.us Brett Millett

    Really enjoying this series. Thanks Andrew!

    Just a quick question…

    How is case in ruby any better than if? Aren’t these equivalent?

    hour = 15

    message = case
    when hour 12 && hour < 17
    "Good Afternoon"
    else
    "Good Evening"
    end

    puts message

    hour = 15

    message = if hour 12 && hour < 17
    "Good Afternoon"
    else
    "Good Evening"
    end

    puts message

    Am I missing something?

    • http://brettic.us Brett Millett

      Guess I should have listened a few seconds more :) There really isn’t much difference. I suppose it’s what you’re more comfortable with. Perhaps like python, ruby doesn’t really have a switch/case statement either.

    • http://brettic.us Brett Millett

      BTW, so much for those CODE tags working. :)

    • http://www.michaeldurrant.com Michael Durrant

      It’s mostlyfor readability and really comes into play when there are more than 2 or 3 options, and more complicated test conditions (to avoid repeating).
      For example, see below. Writing this with if then and multiple elseif statements would be a lot more cumbersome and harder to read.

      grade = ((grade_fraction * 24) + weighting_factor * 300)
      letter_grade = case score
      when 0..9 then “U”
      when 20..29 then “F”
      when 30..39 then “E”
      when 40..49 then “D”
      when 50..59 then “C”
      when 60..69 then “B”
      when 70..100 then “A”
      else “Invalid Score”
      end
      puts letter_grade

      • http://www.michaeldurrant.com Michael Durrant

        sorry line 2 should have “case grade” (not score).

  • http://www.mimrankhan.com Imran Khan

    nice tutorial.. keep going bro.

  • ethan

    I’m pretty sure perl has an unless control structure. I don’t think the unless control structure to too obscure.

  • Beau

    I have copied every line of code from this verbatim. I have even copied and pasted the code from above, and I cannot get past the undefined local variable “make_medium_coffee” error. I am on a Windows platform, and everything has worked to this point. Please advise.

  • http://www.andredublin.com Andre Dublin

    A little expansion on the hour loop here

    <pre name="code" class="html">
    def the_time( hour )
    case hour
    when hour &lt; 12
    puts &quot;Good Morning&quot;
    when 12..17
    puts &quot;Good Afternoon&quot;
    when hour &gt; 17
    puts &quot;Good Evening&quot;
    end
    end

    puts the_time(hour)
    </html>

    Extending the hour loop into a method that accepts an argument (hour)

    • http://www.andredublin.com Andre Dublin

      try that again

      <pre class="js">
      def the_time( hour )
      case hour
      when hour &amp;amp;lt; 12
      puts &amp;amp;quot;Good Morning&amp;amp;quot;
      when 12..17
      puts &amp;amp;quot;Good Afternoon&amp;amp;quot;
      when hour &amp;amp;gt; 17
      puts &amp;amp;quot;Good Evening&amp;amp;quot;
      end
      end

      puts the_time(hour)
      </pre>

  • http://www.andredublin.com Andre Dublin

    You guys should allow ruby code as an option for the pre tags :/

  • http://www.BlaineSch.com BlaineSch

    We had to define the function before we called it, do they have function prototypes in ruby?

  • http://cltblog.com Matthew Tyndall

    Really digging these tuts! Is their a resource you would suggest (screen cast preferably) that will go over object oriented programing. Just want to make sure I am straight with classes, objects, methods and functions. Took a couple classes at school but was never taught in a way that made the lightbulb go off.

  • http://ekinertac.com ekinertac

    Hey andrew!

    i got something awkward in my code

    screenshots of my code

    this one is works right, but it shouldn’t http://d.ekinertac.com/AF7U

    this is the other one it looks awkward http://d.ekinertac.com/xc2b

    i got “nil” for shortened the while loop

  • Ben

    Conditional #1 : elsif – You don’t need to use semi-colons to call a function in ruby, right?

    • Ben

      Sorry didn’t watch till the end…

  • http://twitter.com/andrescristi Andrés Cristi

    Your code is wrong, it says
    order = { :size => “medium” }
    def make_medium_cofee
    puts “making medium statement”
    end
    #assume other functions
    if order[:size] == “small”
    make_small_coffee;
    elsif order[:size] == “medium”
    make_medium_coffee;
    elsif order[:size] == “large”
    make_large_coffee;
    else
    make_coffee;
    end
    and should be
    order = { :size => “medium” }
    def make_medium_coffee
    puts “making medium statement”
    end
    #assume other functions
    if order[:size] == “small”
    make_small_coffee;
    elsif order[:size] == “medium”
    make_medium_coffee;
    elsif order[:size] == “large”
    make_large_coffee;
    else
    make_coffee;
    end