than - ruby case when then




How to write a switch statement in Ruby (14)

How do I write a switch statement in Ruby?


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 the issue that kikito warns.


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

Will print "It is not a string".

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


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

If there is a long list of when's 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'
end

def menu2
  puts 'menu 2'
end

def menu3
  puts 'menu3'
end

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

# Then just call the relevant method from the hash
send(menu[selected_menu])

I've started to use:

a = "secondcase"

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

puts var_name
>> "bar"

It helps compact code in some cases.


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


It is done by case in Ruby. Also see this article 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 (I am using Kindle) of The Ruby Programming Lanugage (1st Edition, O'Reilly), 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.)



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
        break;
    case 'd':
    case 'e':
        // Do something else for d or e
        break;
}

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
end

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.


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

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

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. repl.it test.


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


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

You can do like this in more natural way,

case expression
when condtion1
   function
when condition2
   function
else
   function
end

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.

1st way

age = 20
case 
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end

2nd way

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





conditional