How do I write a switch statement in Ruby?
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".
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.)
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
$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"
else
puts "adult"
end
See "Ruby - if...else, case, unless" for more information.
If you need "less than" or "greater than":
case x
when 1..5
"It's between 1 and 5"
when 6
"It's 6"
when 7..1.0/0
"It's equal or greater than 7"
when -1.0/0..0
"It's equal or less than 0"
end
1.0/0 is equal to Float::INFINITY, so you can use which you prefer.
After Ruby 2.6 you can use Endless Ranges, After Ruby 2.7 you can also use Beginless Ranges, so you can do for example:
case x
when 1..5
"It's between 1 and 5"
when 6
"It's 6"
when (7..)
"It's equal or greater than 7"
when (..0)
"It's equal or less than 0"
end
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'
end
=> "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'
end
=> 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:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
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.
The case statement operator is like switch in the other languages.
This is the syntax of switch...case in C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// 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
.
.
.
else
# statements
end
For example:
x = 10
case x
when 1,2,3
puts "1, 2, or 3"
exit
when 10
puts "10" # it will stop here and execute that line
exit # then it'll exit
else
puts "Some other number"
end
For more information see the case documentation.
We can write switch statement for multiple conditions.
For Example,
x = 22
CASE x
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} "
END
Ruby supports a case expression instead.
Class matching:
case e = StandardError.new("testing")
when Exception then puts "error!"
else puts "ok!"
end # => error!
Multiple value matching:
case 3
when 1,2,3 then puts "1..3"
when 4,5,6 then puts "4..6"
else puts "?"
end # => 1..3
Regex evaluation:
case "monkey"
when /mon/ then puts "banana"
else puts "?"
end # => banana
I prefer to use case + than
number = 10
case number
when 1...8 then # ...
when 8...15 then # ...
when 15.. then # ...
end
Ruby introduced pattern matching in 2.7
It is super powerful feature
It also use case, but have another syntax
There is also find pattern feature
users =
{ users:
[
{ user: 'user', email: 'user@user.com' },
{ user: 'admin', email: 'admin@admin.com' },
]
}
case users
in users: [*, { user:, email: /admin/ => admin_email }, *]
puts admin_email
else
puts "No admin"
end
# will print admin@admin.com
Unlike the usual case, if the conditions are not matched, NoMatchingPatternError will be thrown. So you may have to use the else branch