How to write a switch statement in Ruby

ID : 373

viewed : 92

Tags : rubyswitch-statementconditional-statementsruby

Top 5 Answer for How to write a switch statement in Ruby

vote vote

91

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" else   "You gave me #{x} -- I have no idea what to do with that." end 

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".

vote vote

81

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') else   print('It is not a string or number') end 

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 from case obj.class:

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

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.

vote vote

71

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

Quoted:

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' else   puts 'Only single-digit numbers are allowed' end 

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" end  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.)

vote vote

60

case...when

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" else   puts "Any other thing" end 

Without parameter:

case 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]" end 

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

vote vote

58

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' end 

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

Moddable = Struct.new(:n) do   def ===(numeric)     numeric % n == 0   end end  mod4 = Moddable.new(4) mod3 = Moddable.new(3)  case number when mod4 then puts 'multiple of 4' when mod3 then puts 'multiple of 3' end 

(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   end end  four_wheeler = Vehicle.new 4 two_wheeler = Vehicle.new 2  case vehicle when two_wheeler   puts 'two wheeler' when four_wheeler   puts 'four wheeler' end 

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

Top 3 video Explaining How to write a switch statement in Ruby

Related QUESTION?