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
# Compact syntax with colons
# (no longer supported in Ruby 1.9)
[variable =] case expression
when something: statement
when something: statement
else statement # no colon 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
case
when
when
else
end
April 19, 2008 at 3:50 am |
Super! I just find this info yesterday. Very useful, thank you!
May 5, 2008 at 7:57 pm |
can you use a case in a view? if so how?
May 6, 2008 at 2:29 pm |
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
%>
September 9, 2009 at 1:51 pm |
this is awesome!
February 11, 2009 at 6:06 pm |
Great! I use this post quite often as reference because I always keep forgetting how to write that :-)
March 23, 2009 at 11:42 am |
wow! nice. thanks.
April 19, 2009 at 4:39 am |
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.
April 20, 2009 at 4:04 pm |
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 ?
April 20, 2009 at 4:47 pm |
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 “1\n”.
To fix this, convert the value to an integer before comparing it to 1, 2, or 3:
case value.to_i
Hope that helps!
April 21, 2009 at 4:09 pm |
it worked. thank u sir
April 24, 2009 at 11:16 am |
Hey, cool tips. Perhaps I’ll buy a glass of beer to that person from that chat who told me to visit your site :)
June 14, 2009 at 11:04 pm |
[...] How to write case (switch) statements in Ruby (tags: ruby programming) [...]
June 30, 2009 at 7:46 am |
Thanks for the help with the array example. It helped simplify my code.
July 24, 2009 at 5:47 am |
Thanks, this is awesome :)
Did I mention that I love Rails?
August 11, 2009 at 5:20 am |
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.
February 21, 2011 at 9:40 pm |
“Except you’re not that much like me so you didn’t. But I did.”
Ha! thanks…
November 11, 2011 at 6:06 am |
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.
July 11, 2012 at 9:47 am |
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?
July 11, 2012 at 10:00 am |
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).
July 12, 2012 at 1:00 am
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.