How to write case (switch) statements in Ruby

If you’re like me, when you started coding in Ruby last year you found the “case” statement intriguing. After years of writing in C++ and C# it was hard for you to remember Ruby’s case syntax because it can do so much more than switch statements in those languages.

So you wrote these notes to yourself as you discovered its capabilities. Except you’re not that much like me so you didn’t. But I did. I hope you find them useful.

switch/case syntaxes
(remember: Ruby uses "case" and "when"
where others use "switch" and "case"):

# Basically if/elsif/else (notice there's nothing
# after the word "case"):
[variable = ] case
when bool_condition
  statements
when bool_condition
  statements
else # the else clause is optional
  statements
end
# If you assigned 'variable =' before the case,
# the variable now has the value of the
# last-executed statement--or nil if there was
# no match.  variable=if/elsif/else does this too.

# It's common for the "else" to be a 1-line
# statement even when the cases are multi-line:
[variable = ] case
when bool_condition
  statements
when bool_condition
  statements
else statement
end

# Case on an expression:
[variable = ] case expression
when nil
  statements execute if the expr was nil
when Type1 [ , Type2 ] # e.g. Symbol, String
  statements execute if the expr
  resulted in Type1 or Type2 etc.
when value1 [ , value2 ]
  statements execute if the expr
  equals value1 or value2 etc.
when /regexp1/ [ , /regexp2/ ]
  statements execute if the expr
  matches regexp1 or regexp 2 etc.
when min1..max1 [ , min2..max2 ]
  statements execute if the expr is in the range
  from min1 to max1 or min2 to max2 etc.
  (use 3 dots min...max to go up to max-1)
else
  statements
end

# When using case on an expression you can mix &
# match different types of expressions. E.g.,
[variable =] case expression
when nil, /regexp/, Type
  statements execute when the expression
  is nil or matches the regexp or results in Type
when min..max, /regexp2/
  statements execute when the expression is
  in the range from min to max or matches regexp2
end

# You can combine matches into an array and
# precede it with an asterisk. This is useful when
# the matches are defined at runtime, not when
# writing the code. The array can contain a
# combination of match expressions
# (strings, nil, regexp, ranges, etc.)
[variable =] case expression
when *array_1
  statements execute when the expression matches one
  of the elements of array_1
when *array_2
  statements execute when the expression matches one
  of the elements of array_2
end

# Compact syntax with 'then':
[variable =] case expression
when something then statement
when something then statement
else statement
end

# Compact syntax with semicolons:
[variable =] case expression
when something; statement
when something; statement
else statement # no semicolon required
end

# 1-line syntax:
[variable = ] case expr when {Type|value}
  statements
end

# Formatting: it's common to indent the "when"
# clauses and it's also common not to.
case
  when
  when
  else
end

# More idiomatic:
case
when
when
else
end

20 thoughts on “How to write case (switch) statements in Ruby”

  1. Great question, Rashantha. I assume you mean in a Rails View. The trick is to use %=, not %. Here’s an example:

    <%=
      case @results
      when nil then "No results"
      else @results.join ", "
      end
    %>

  2. hi how to use case statement when the input is from the user (i.e.)using gets.i tried but it executes the default statement.

  3. im going to create a adressbook in Ruby using XML.
    My options are
    1.List – List the XML file.
    2.Add – Add an element into the XML file
    3.Delete – Delete an element from the XML file
    i want to put these three options in case statements and select one based on the user input.
    value = gets (receive input from the user)
    case value
    when 1: list (invoke list)
    when 2: add (invoke add)
    when 3: delete (invoke delete)
    else puts “exit”
    When i give input as 1,2,or 3 only else statement is executed.
    Is the syntax is right?what corrections i have to do ?

  4. Hi Raji,

    I believe the problem is your case statement is comparing a string with an integer. Type “value=gets” into IRB and then type the number 1. You’ll see that IRB tells you the result is the string “1n”.

    To fix this, convert the value to an integer before comparing it to 1, 2, or 3:
    case value.to_i

    Hope that helps!

  5. ahh, thank goodness for this post. The pickaxe was entirely opaque on this subject and I now know how to do if-else’s neatly AND switches all with one structure.

    Many thanks.

  6. every since my first C class in college i have always munged the switch/case. Now that I now almost a dozen different languages. Its hopeless in remembering the syntax. Awesome post and example! Thanks.

  7. I have a problem with the case in Ruby while trying to parse something that goes over communication line. The relevant code part is:

    status=”"
    status=cmd.ParseANSIString()
    case status
    when “READY”
    Monitor().SetStateName(“Ready”)
    when “RUN”
    Monitor().SetStateName(“Collecting”)
    when “PAUSE”
    Monitor().SetStateName(“Wasting”)
    else
    Monitor().SetStateName(status)
    end

    Instrument is in the READY state, however, I always fall into the else clause (outputting READY to the SetStateName). The frame is of exact length, no control characters before or after…

    I am quite clueless… can you help, please?

    1. Daniel, I would check to see if status is an *exact* match or not. E.g., look for whitespace at the beginning or end of the string (.strip) and make sure it is uppercase (.upcase).

      1. Thanks, Brian, .strip did the trick. I was quite sure the contents of the string are exact (I have tried to cut the length of the frame in another function by one to see what will be the output, and it was “READ”), but it clearly is not the case and there is some control character added somewhere.

        Once more, thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *

Feel free to use <a>, <b>, <i>, <strong>, <em>, <strike>, <code>.

Code blocks:
[code language="ruby/javascript/html/css/sass/bash"]
[/code]