By Readonly

2009-06-04 01:18:00 8 Comments

How do I write a switch statement in Ruby?


@nonopolarity 2009-06-04 01:20:35

It is done using case in Ruby. Also see "Switch statement" on Wikipedia.


case n
when 0
  puts 'You typed zero'
when 1, 9
  puts 'n is a perfect square'
when 2
  puts 'n is a prime number'
  puts 'n is an even number'
when 3, 5, 7
  puts 'n is a prime number'
when 4, 6, 8
  puts 'n is an even number'
  puts 'Only single-digit numbers are allowed'

Another example:

score = 70

result = case score
   when 0..40 then "Fail"
   when 41..60 then "Pass"
   when 61..70 then "Pass with Merit"
   when 71..100 then "Pass with Distinction"
   else "Invalid Score"

puts result

On around page 123 of The Ruby Programming Language (1st Edition, O'Reilly) on my Kindle, it says the then keyword following the when clauses can be replaced with a newline or semicolon (just like in the if then else syntax). (Ruby 1.8 also allows a colon in place of then, but this syntax is no longer allowed in Ruby 1.9.)

@Andrew Grimm 2011-04-17 23:49:45

when (-1.0/0.0)..-1 then "Epic fail"

@onebree 2015-05-12 14:06:10

This is the answer I used, because I am defining a variable based on the results of a case switch. Rather than saying type = #{score} each line, I can simply copy what you did. Much more elegant I also like the one-liners much better (if possible)

@Nick Moore 2020-01-20 16:15:58

I know this is unrelated to the essence of the answer, but 4 is also a perfect square.

@Alexander 2014-09-18 14:48:15

Depending on your case, you could prefer to use a hash of methods.

If there is a long list of whens and each of them has a concrete value to compare with (not an interval), it will be more effective to declare a hash of methods and then to call the relevant method from the hash like that.

# Define the hash
menu = {a: :menu1, b: :menu2, c: :menu2, d: :menu3}

# Define the methods
def menu1
  puts 'menu 1'

def menu2
  puts 'menu 2'

def menu3
  puts 'menu3'

# Let's say we case by selected_menu = :a
selected_menu = :a

# Then just call the relevant method from the hash

@ysk 2017-02-16 09:32:15

You can write case expressions in two different ways in Ruby:

  1. Similar to a series of if statements
  2. Specify a target next to the case and each when clause is compared to the target.
age = 20
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
puts "default condition"


case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'

@user1438038 2017-02-16 10:16:15

Though your code might answer the question, you should add at least a short description on what your code does and how it solves the initial problem.

@ysk 2017-04-05 11:59:01

I will consider this tip in future.

@BrunoFacca 2016-07-06 16:07:17

As stated in many of the above answers, the === operator is used under the hood on case/when statements.

Here is additional information about that operator:

Case equality operator: ===

Many of Ruby's built-in classes, such as String, Range, and Regexp, provide their own implementations of the === operator, also known as "case-equality", "triple equals" or "threequals". Because it's implemented differently in each class, it will behave differently depending on the type of object it was called on. Generally, it returns true if the object on the right "belongs to" or "is a member of" the object on the left. For instance, it can be used to test if an object is an instance of a class (or one of its sub-classes).

String === "zen"  # Output: => true
Range === (1..2)   # Output: => true
Array === [1,2,3]   # Output: => true
Integer === 2   # Output: => true

The same result can be achieved with other methods which are probably best suited for the job, such as is_a? and instance_of?.

Range Implementation of ===

When the === operator is called on a range object, it returns true if the value on the right falls within the range on the left.

(1..4) === 3  # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6  # Output: => false

("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false

Remember that the === operator invokes the === method of the left-hand object. So (1..4) === 3 is equivalent to (1..4).=== 3. In other words, the class of the left-hand operand will define which implementation of the === method will be called, so the operand positions are not interchangeable.

Regexp Implementation of ===

Returns true if the string on the right matches the regular expression on the left.

/zen/ === "practice zazen today"  # Output: => true
# is similar to
"practice zazen today"=~ /zen/

The only relevant difference between the two examples above is that, when there is a match, === returns true and =~ returns an integer, which is a truthy value in Ruby. We will get back to this soon.

@Navneet 2017-11-13 07:58:42

$age =  5
case $age
when 0 .. 2
   puts "baby"
when 3 .. 6
   puts "little child"
when 7 .. 12
   puts "child"
when 13 .. 18
   puts "youth"
   puts "adult"

See "Ruby - if...else, case, unless" for more information.

@Ben96 2019-11-01 13:35:22

The case statement operator is like switch in the other languages.

This is the syntax of in C:

switch (expression)
    case constant1:
      // statements
    case constant2:
      // statements
      // default statements

This is the syntax of case...when in Ruby:

case expression
  when constant1, constant2 #Each when statement can have multiple candidate values, separated by commas.
     # statements 
     next # is like continue in other languages
  when constant3
     # statements 
     exit # exit is like break in other languages
     # statements

For example:

x = 10
case x
when 1,2,3
  puts "1, 2, or 3"
when 10
  puts "10" # it will stop here and execute that line
  exit # then it'll exit
  puts "Some other number"

For more information see the case documentation.

@Donato 2019-03-20 20:16:13

It's critical to emphasize the comma (,) in a when clause. It acts as an || of an if statement, that is, it does an OR comparison and not an AND comparison between the delimited expressions of the when clause. See the following case statement:

x = 3
case x
  when 3, x < 2 then 'apple'
  when 3, x > 2 then 'orange'
 => "apple"

x is not less than 2, yet the return value is "apple". Why? Because x was 3 and since ',`` acts as an||, it did not bother to evaluate the expressionx < 2'.

You might think that to perform an AND, you can do something like this below, but it doesn't work:

case x
  when (3 && x < 2) then 'apple'
  when (3 && x > 2) then 'orange'
 => nil 

It doesn't work because (3 && x > 2) evaluates to true, and Ruby takes the True value and compares it to x with ===, which is not true, since x is 3.

To do an && comparison, you will have to treat case like an if/else block:

  when x == 3 && x < 2 then 'apple'
  when x == 3 && x > 2 then 'orange'

In the Ruby Programming Language book, Matz says this latter form is the simple (and infrequently used) form, which is nothing more than an alternative syntax for if/elsif/else. However, whether it is infrequently used or not, I do not see any other way to attach multiple && expressions for a given when clause.

@sondra.kinsey 2019-05-20 13:40:18

This doesn't seem like good coding style to me. Using a rare alternate syntax unnecessarily obfuscates. Why not use normal if...elsif? It seems you're trying to mix a case statement and a condition. Why? Just put the conditional inside the when block, eg. when 3; ( x < 2 ) ? 'apple' : 'orange'

@jmansurf 2013-08-06 20:18:37

Lots of great answers but I thought I would add one factoid.. If you are attempting to compare objects (Classes) make sure you have a space ship method (not a joke) or understand how they are being compared

"Ruby Equality And Object Comparison" is a good discussion on the topic.

@the Tin Man 2013-09-11 15:18:42

For reference, the "space-ship" method is <=>, which is used to return -1, 0, 1, or nil depending on whether the comparison returns less-than, equal, greater-than, or not-comparable respectively. Ruby's Comparable module documentation explains it.

@Lahiru 2016-07-18 19:59:10

Ruby uses the case for writing switch statements.

As per the case documentation:

Case statements consist of an optional condition, which is in the position of an argument to case, and zero or more when clauses. The first when clause to match the condition (or to evaluate to Boolean truth, if the condition is null) “wins”, and its code stanza is executed. The value of the case statement is the value of the successful when clause, or nil if there is no such clause.

A case statement can end with an else clause. Each when a statement can have multiple candidate values, separated by commas.


case x
when 1,2,3
  puts "1, 2, or 3"
when 10
  puts "10"
  puts "Some other number"

Shorter version:

case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"

And as "Ruby's case statement - advanced techniques" describes Ruby case;

Can be used with Ranges:

case 5
when (1..10)
  puts "case statements match inclusion in a range"

## => "case statements match inclusion in a range"

Can be used with Regex:

case "FOOBAR"
when /BAR$/
  puts "they can match regular expressions!"

## => "they can match regular expressions!"

Can be used with Procs and Lambdas:

case 40
when -> (n) { n.to_s == "40" }
  puts "lambdas!"

## => "lambdas"

Also, can be used with your own match classes:

class Success
  def self.===(item)
    item.status >= 200 && item.status < 300

class Empty
  def self.===(item)
    item.response_size == 0

case http_response
when Empty
  puts "response was empty"
when Success
  puts "response was a success"

@Manish Shrivastava 2014-07-03 06:46:12

If you are eager to know how to use an OR condition in a Ruby switch case:

So, in a case statement, a , is the equivalent of || in an if statement.

case car
   when 'Maruti', 'Hyundai'
      # Code here

See "How A Ruby Case Statement Works And What You Can Do With It".

@froderik 2018-12-23 16:54:20

code formatting is not working in the linked article :-)

@mmdemirbas 2012-07-05 13:19:42


To add more examples to Chuck's answer:

With parameter:

case a
when 1
  puts "Single value"
when 2, 3
  puts "One of comma-separated values"
when 4..6
  puts "One of 4, 5, 6"
when 7...9
  puts "One of 7, 8, but not 9"
  puts "Any other thing"

Without parameter:

when b < 3
  puts "Little than 3"
when b == 3
  puts "Equal to 3"
when (1..10) === b
  puts "Something in closed range of [1..10]"

Please, be aware of "How to write a switch statement in Ruby" that kikito warns about.

@sixty4bit 2014-12-09 20:19:52

Thanks, this was helpful for having multiple options on one line. I had been trying to use or

@kikito 2011-04-17 15:20:14

case...when behaves a bit unexpectedly when handling classes. This is due to the fact that it uses the === operator.

That operator works as expected with literals, but not with classes:

1 === 1           # => true
Fixnum === Fixnum # => false

This means that if you want to do a case ... when over an object's class, this will not work:

obj = 'hello'
case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
  print('It is not a string or number')

Will print "It is not a string or number".

Fortunately, this is easily solved. The === operator has been defined so that it returns true if you use it with a class and supply an instance of that class as the second operand:

Fixnum === 1 # => true

In short, the code above can be fixed by removing the .class:

obj = 'hello'
case obj  # was case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
  print('It is not a string or number')

I hit this problem today while looking for an answer, and this was the first appearing page, so I figured it would be useful to others in my same situation.

@Sugumar Venkatesan 2017-02-10 09:59:54

obj='hello';case obj; when 'hello' then puts "It's hello" end

@lindes 2019-04-11 07:14:14

Having the .class part in is interesting to note, thanks. Of course, this is entirely appropriate behavior (though I could see how it might be a common mistake to think that would print It is a string)... you're testing the class of some arbitrary object, not the object itself. So, for example: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end results in: "Class!" This works the same for 1.class, {}.class, etc. Dropping .class, we get "String!" or "Something else" for these various values.

@Foram Thakral 2019-01-25 07:32:41

We can write switch statement for multiple conditions.

For Example,

x = 22

  WHEN 0..14 THEN puts "#{x} is less than 15"    
  WHEN 15 THEN puts "#{x} equals 15" 
  WHEN 15 THEN puts "#{x} equals 15" 
  WHEN 15..20 THEN puts "#{x} is greater than 15" 
  ELSE puts "Not in the range, value #{x} " 

@sondra.kinsey 2019-05-20 13:42:07

This won't work; Ruby keywords (eg. case, when, end) are case-sensitive and cannot be uppercase like this.

@the Tin Man 2019-11-26 19:59:41

NoMethodError (undefined method CASE' for main:Object)`. As @sondra.kinsey said, you can't use upper-case. Ruby will think it's a CONSTANT.

@CPHPython 2018-04-18 11:29:29

No support for regular expressions in your environment? E.g. Shopify Script Editor (April, 2018):

[Error]: uninitialized constant RegExp

A workaround following a combination of methods already previously covered in here and here:

code = '!ADD-SUPER-BONUS!'

class StrContains
  def self.===(item)
    item.include? 'SUPER' or item.include? 'MEGA' or\
    item.include? 'MINI' or item.include? 'UBER'

case code.upcase
when '12345PROMO', 'CODE-007', StrContains
  puts "Code #{code} is a discount code!"
when '!ADD-BONUS!'
  puts 'This is a bonus code!'
  puts 'Sorry, we can\'t do anything with the code you added...'

I used ors in the class method statement since || has higher precedence than .include?. If you are a ruby-nazi, please imagine I used this (item.include? 'A') || ... instead. test.

@Chuck 2009-06-04 01:22:57

Ruby uses the case expression instead.

case x
when 1..5
  "It's between 1 and 5"
when 6
  "It's 6"
when "foo", "bar"
  "It's either foo or bar"
when String
  "You passed a string"
  "You gave me #{x} -- I have no idea what to do with that."

Ruby compares the object in the when clause with the object in the case clause using the === operator. For example, 1..5 === x, and not x === 1..5.

This allows for sophisticated when clauses as seen above. Ranges, classes and all sorts of things can be tested for rather than just equality.

Unlike switch statements in many other languages, Ruby’s case does not have fall-through, so there is no need to end each when with a break. You can also specify multiple matches in a single when clause like when "foo", "bar".

@Automatico 2013-01-20 15:34:23

You can also do regex on the passed argument: when /thisisregex/ next line puts "This is the found match nr. 1 #{$1}" end

@Alexander - Reinstate Monica 2018-05-11 23:40:43

Also worth noting, you can shorten your code by putting the when and return statement on the same line: when "foo" then "bar"

@janniks 2018-09-03 09:45:57

Important: Unlike switch statements in many other languages, Ruby’s case does NOT have fall-through, so there is no need to end each when with a break.

@Clint Pachl 2019-06-04 23:05:04

So many up votes yet not even a mention of the keyword then. Please also see the other answers.

@DigitalRoss 2016-02-05 20:40:16

It's called case and it works like you would expect, plus lots more fun stuff courtesy of === which implements the tests.

case 5
  when 5
    puts 'yes'
    puts 'else'

Now for some fun:

case 5 # every selector below would fire (if first)
  when 3..7    # OK, this is nice
  when 3,4,5,6 # also nice
  when Fixnum  # or
  when Integer # or
  when Numeric # or
  when Comparable # (?!) or
  when Object  # (duhh) or
  when Kernel  # (?!) or
  when BasicObject # (enough already)

And it turns out you can also replace an arbitrary if/else chain (that is, even if the tests don't involve a common variable) with case by leaving out the initial case parameter and just writing expressions where the first match is what you want.

  when x.nil?
  when (x.match /'^fn'/)
  when (x.include? 'substring')
  when x.gsub('o', 'z') == 'fnzrq'

@Navin 2016-05-26 09:15:12

You can do like this in more natural way,

case expression
when condtion1
when condition2

@Robert Kajic 2013-12-07 12:11:35

Many programming languages, especially those derived from C, have support for the so-called Switch Fallthrough. I was searching for the best way to do the same in Ruby and thought it might be useful to others:

In C-like languages fallthrough typically looks like this:

switch (expression) {
    case 'a':
    case 'b':
    case 'c':
        // Do something for a, b or c
    case 'd':
    case 'e':
        // Do something else for d or e

In Ruby, the same can be achieved in the following way:

case expression
when 'a', 'b', 'c'
  # Do something for a, b or c
when 'd', 'e'
  # Do something else for d or e

This is not strictly equivalent, because it's not possible to let 'a' execute a block of code before falling through to 'b' or 'c', but for the most part I find it similar enough to be useful in the same way.

@Prabhakar Undurthi 2016-03-12 06:33:17

puts "Recommend me a language to learn?"
input = gets.chomp.downcase.to_s

case input
when 'ruby'
    puts "Learn Ruby"
when 'python'
    puts "Learn Python"
when 'java'
    puts "Learn Java"
when 'php'
    puts "Learn PHP"
    "Go to Sleep!"

@the Tin Man 2019-11-26 20:16:20

It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code.

@deepfritz 2014-07-07 21:18:24

I've started to use:

a = "secondcase"

var_name = case a
  when "firstcase" then "foo"
  when "secondcase" then "bar"

puts var_name
>> "bar"

It helps compact code in some cases.

@Tom Lord 2016-07-15 14:55:20

Code like this should usually be done using a Hash, rather than a case statement.

@the Tin Man 2019-11-26 19:38:51

Using a hash would be faster when that switch gets big.

@123 2014-01-20 11:45:28

Multi-value when and no-value case:

print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
  puts 'You pretty smart!'
when "C", "D"
  puts 'You pretty dumb!!'
  puts "You can't even use a computer!"

And a regular expression solution here:

print "Enter a string: "
some_string = gets.chomp
when some_string.match(/\d/)
  puts 'String has numbers'
when some_string.match(/[a-zA-Z]/)
  puts 'String has letters'
  puts 'String has no numbers or letters'

@tckmn 2014-01-26 03:21:15

why not just case some_string, when /\d/, (stuff), when /[a-zA-Z]/, (stuff), end (where , means newline)

@tckmn 2014-01-26 03:22:55

oh, and the first part is already covered in this answer, and many answers already mention regex. Frankly, this answer adds nothing new, and I'm downvoting and voting to delete it.

@123 2014-01-27 05:19:43

@DoorknobofSnow This is to show that you can use Regex solution and comma seperated values in switch case. Not sure why the solution is giving you so much ache.

@Mike Graf 2014-06-20 18:48:38

so if they got a "F", a legit grade, its their fault your code is missing a case?

@emery 2015-05-07 14:14:22

I like the humor of this, and the fact that it demonstrates that you can match strings to a case.

@CPHPython 2018-04-18 09:57:59

@Doorknob I also agree that this is just a repetition of previous answers, but the fact that he presented instead an empty case using the .match() method is indeed an alternative answer to the first and previous Regex answer in here. I can't see how and why this method would be preferable though...

@Sonu Oommen 2013-11-05 07:29:51

Since switch case always returns a single object, we can directly print its result:

puts case a
     when 0
        "It's zero"
     when 1
        "It's one"

@James Lim 2013-08-01 00:04:53

In Ruby 2.0, you can also use lambdas in case statements, as follows:

is_even = ->(x) { x % 2 == 0 }

case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'

You can also create your own comparators easily using a Struct with a custom ===

Moddable = do
  def ===(numeric)
    numeric % n == 0

mod4 =
mod3 =

case number
when mod4 then puts 'multiple of 4'
when mod3 then puts 'multiple of 3'

(Example taken from "Can procs be used with case statements in Ruby 2.0?".)

Or, with a complete class:

class Vehicle
  def ===(another_vehicle)
    self.number_of_wheels == another_vehicle.number_of_wheels

four_wheeler = 4
two_wheeler = 2

case vehicle
when two_wheeler
  puts 'two wheeler'
when four_wheeler
  puts 'four wheeler'

(Example taken from "How A Ruby Case Statement Works And What You Can Do With It".)

@Haris Krajina 2012-10-16 12:17:41

You can use regular expressions, such as finding a type of string:

case foo
when /^(true|false)$/
   puts "Given string is boolean"
when /^[0-9]+$/ 
   puts "Given string is integer"
when /^[0-9\.]+$/
   puts "Given string is float"
   puts "Given string is probably string"

Ruby's case will use the equality operand === for this (thanks @JimDeville). Additional information is available at "Ruby Operators". This also can be done using @mmdemirbas example (without parameter), only this approach is cleaner for these types of cases.

Related Questions

Sponsored Content

16 Answered Questions

[SOLVED] Why can't I use switch statement on a String?

20 Answered Questions

[SOLVED] How to call shell commands from Ruby

  • 2008-08-05 12:56:52
  • CodingWithoutComments
  • 531918 View
  • 1084 Score
  • 20 Answer
  • Tags:   ruby shell interop

10 Answered Questions

[SOLVED] Multi-Line Comments in Ruby?

  • 2010-06-07 13:11:05
  • Mohit Jain
  • 413511 View
  • 751 Score
  • 10 Answer
  • Tags:   ruby comments

23 Answered Questions

[SOLVED] Why can't variables be declared in a switch statement?

33 Answered Questions

[SOLVED] How do I get the current absolute URL in Ruby on Rails?

19 Answered Questions

[SOLVED] What is attr_accessor in Ruby?

  • 2010-12-06 21:07:06
  • dennismonsewicz
  • 466430 View
  • 1028 Score
  • 19 Answer
  • Tags:   ruby

21 Answered Questions

[SOLVED] Switch statement multiple cases in JavaScript

10 Answered Questions

[SOLVED] How to convert a string to lower or upper case in Ruby

44 Answered Questions

[SOLVED] Replacements for switch statement in Python?

7 Answered Questions

[SOLVED] How to write to file in Ruby?

  • 2010-05-06 01:11:39
  • ohana
  • 594399 View
  • 572 Score
  • 7 Answer
  • Tags:   ruby file-io

Sponsored Content