andrewjadams3
andrewjadams3

Reputation: 32

Looping through a case statement in Ruby?

I am trying to determine the best way to loop through a case statement until a user provides a certain input (in this case, exit).

So far, my code works with a while loop, but it seems a little redundant when I have input = gets.chomp over and over.

Here's a bit of abbreviated code:

input = gets.chomp

while input.downcase != 'exit'
  case input.downcase
    when 'help'
      puts "Available commands are..."
      input = gets.chomp

    #more when statements go here...

    else 
      puts "That is not a valid command. Type 'HELP' for available commands."
      input = gets.chomp
  end
end

puts "Goodbye!"

Upvotes: 0

Views: 3812

Answers (3)

Tom Fenech
Tom Fenech

Reputation: 74625

Why don't you change the while to:

while (input = gets.chomp.downcase) != 'exit'

Note that this also means that instead of using case input.downcase, you can use case input, as it has already been made lowercase.

edit: my roots in C betray me...

As mentioned in the comments, this is not a particularly "ruby-esque" solution. It also causes a stack trace when gets returns nil. You might prefer to split it into two lines:

while (input = gets)
  input = input.chomp.downcase
  break if input == 'exit'

  case input

  # when statements

  else
    puts "That is not a valid command. Type 'HELP' for available commands."
  end
end

I separated the "exit" from the case criteria for a couple of reasons:

  1. It was part of the loop logic in the question, so it's (arguably) more readable to keep it separate from the other cases.
  2. I didn't realise that break behaves differently in Ruby case statements to other languages that I am more familiar with, so I didn't think it would do what you wanted.

You could equally well do this:

while (input = gets)
  case input.chomp.downcase
  when 'exit'
    break        

  # other when statements

  else
    puts "That is not a valid command. Type 'HELP' for available commands."
  end
end

edit: I am delighted to hear that like Perl, Ruby also has the $_ variable, to which the value of gets will be assigned:

while gets
  case $_.chomp.downcase
  when 'exit'
    break        

  # other when statements

  else
    puts "That is not a valid command. Type 'HELP' for available commands."
  end
end

Upvotes: 2

the Tin Man
the Tin Man

Reputation: 160549

I'd write it like:

loop do

  input = gets.chomp.downcase

  case input
  when 'help'
    puts "Available commands are..."

    # more when statements go here...
  when 'exit'
    break

  else
    puts "That is not a valid command. Type 'HELP' for available commands."
  end

end

puts "Goodbye!"

A loop is designed for this sort of case, where you just want to loop cleanly, and then eventually break out on some condition.

For ultimate clarity in what the code is doing, I'd put the exit immediately after reading the input, instead of being embedded in the case statements. It's a minor thing, but is useful to remember if you're coding and others have to help maintain it:

loop do

  input = gets.chomp.downcase
  break if input == 'exit'

  case input
  when 'help'
    puts "Available commands are..."

    # more when statements go here...

  else
    puts "That is not a valid command. Type 'HELP' for available commands."
  end

end

puts "Goodbye!"

Upvotes: 3

Tobias Schoknecht
Tobias Schoknecht

Reputation: 550

You can even get rid of input by exiting the loop with break instead of checking the result in the while condition

while true
  case gets.chomp.downcase
    when 'exit'
      break
    when 'help'
      # stuff
    else
      # other stuff
  end
end

Upvotes: 1

Related Questions