Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Ruby Dictionary

  1. Home
  2. Ruby Dictionary
  3. case / when (Ruby)

case / when (Ruby)

The case/when construct in Ruby is a syntax for writing multi-branch conditional logic concisely. Internally it uses the === operator for matching, so you can specify not only numbers and strings but also range objects, regular expressions, and class names as conditions.

Syntax

# Basic syntax
case target_value
when value1
  # Executed when value1 matches (omitting then is the common style)
when value2, value3
  # Executed when either value2 or value3 matches (multi-value match)
when range
  # Matches against a Range object
when /regexp/
  # Matches against a regular expression
when ClassName
  # Checks whether the target is an instance of that class
else
  # Executed when no when clause matches
end

# Inline style using then (useful for putting everything on one line)
case target_value
when value1 then action1
when value2 then action2
end

# Can be used as an expression (the last evaluated expression becomes the value)
result = case target_value
         when value1 then "A"
         when value2 then "B"
         else          "C"
         end

Keywords and Match Patterns

ExpressionDescription
when valueMatches the target value using the === operator. The block is executed on a match.
when value1, value2Lists multiple values separated by commas. Executes if any one of them matches.
when rangeUses Range#=== to check whether the target value falls within the range.
when /regexp/Uses Regexp#=== to check whether the target string matches the pattern.
when ClassNameUses Module#=== to check whether the target is an instance of that class.
thenUsed to put a when clause and its action on a single line. Can be omitted.
elseExecuted when no when clause matches. Can be omitted.

Sample Code

Determining the role of Steins;Gate characters. A basic example of matching against string literals and using an else clause.

character_role.rb
characters = ["Okabe Rintaro", "Makise Kurisu", "Shiina Mayuri", "Hashida Itaru", "Kiryuu Moeka"]

characters.each do |name|
  role = case name
         when "Okabe Rintaro"  then "Director of the Future Gadget Lab — self-proclaimed mad scientist"
         when "Makise Kurisu"  then "Genius scientist — co-developer of the time machine theory"
         when "Shiina Mayuri"  then "Childhood friend — cosplay designer"
         when "Hashida Itaru"  then "Daru — super hacker"
         else                       "Lab member (details unknown)"
         end
  puts "#{name}: #{role}"
end
ruby character_role.rb
Okabe Rintaro: Director of the Future Gadget Lab — self-proclaimed mad scientist
Makise Kurisu: Genius scientist — co-developer of the time machine theory
Shiina Mayuri: Childhood friend — cosplay designer
Hashida Itaru: Daru — super hacker
Kiryuu Moeka: Lab member (details unknown)

Matching against a numeric Range. Changes the message based on Okabe Rintaro's time leap count.

leap_count.rb
# Range#=== is used, giving the same result as between?
leap_count = 23

message = case leap_count
           when 0
             "No time leaps yet."
           when 1..5
             "Early-stage time leaps."
           when 6..15
             "Getting closer to the truth through repetition."
           when 16..Float::INFINITY
             "Almost reached the Beta world line."
           end

puts "Time leap #{leap_count}: #{message}"
ruby leap_count.rb
Time leap 23: Almost reached the Beta world line.

Matching against regular expressions. Determines the pattern of Makise Kurisu's handle names.

handle_check.rb
handles = ["Christina", "Kurisu_0571", "assistant", "hououin_kyouma_777", "mayuri*"]

handles.each do |handle|
  category = case handle
             when /\A[A-Z][a-z]+\z/
               "Real-name style handle"
             when /\A\w+_\d+\z/
               "User ID style handle"
             when /\Aassistant\z/i
               "Assistant account"
             when /[^a-zA-Z0-9_]/
               "Handle containing special characters"
             else
               "Standard handle"
             end
  puts "#{handle}: #{category}"
end
ruby handle_check.rb
Christina: Real-name style handle
Kurisu_0571: User ID style handle
assistant: Assistant account
hououin_kyouma_777: User ID style handle
mayuri*: Handle containing special characters

Matching against class names. Switches processing based on the type of lab member data.

type_dispatch.rb
# Module#=== is used, equivalent to is_a?
lab_data = ["Okabe Rintaro", 18, 3.14, :kurisu, nil, true]

lab_data.each do |item|
  description = case item
                when String
                  "String: \"#{item}\""
                when Integer
                  "Integer: #{item} (lab member number)"
                when Float
                  "Float: #{item}"
                when Symbol
                  "Symbol: #{item}"
                when NilClass
                  "nil: no value"
                when TrueClass, FalseClass
                  "Boolean: #{item}"
                end
  puts description
end
ruby type_dispatch.rb
String: "Okabe Rintaro"
Integer: 18 (lab member number)
Float: 3.14
Symbol: kurisu
nil: no value
Boolean: true

Multi-value matching. Groups lab members by affiliation using comma-separated when values.

group_match.rb
members = ["Okabe Rintaro", "Makise Kurisu", "Shiina Mayuri", "Hashida Itaru", "Kiryuu Moeka"]

members.each do |name|
  group = case name
          when "Okabe Rintaro", "Shiina Mayuri", "Hashida Itaru"
            "Founding members"
          when "Makise Kurisu", "Kiryuu Moeka"
            "Later members"
          else
            "Other"
          end
  puts "#{name}: #{group}"
end
ruby group_match.rb
Okabe Rintaro: Founding members
Makise Kurisu: Later members
Shiina Mayuri: Founding members
Hashida Itaru: Founding members
Kiryuu Moeka: Later members

Overview

Ruby's case/when construct uses the === operator internally for matching. For integers and strings a normal equality comparison is performed, while Range performs a range membership check equivalent to include?, Regexp performs pattern matching, and Module performs an instance check. The behavior switches automatically based on the class of the match target, letting you write diverse conditions intuitively without worrying about type checks.

then is used when you want to write a when clause and its action on a single line. When multiple lines of processing follow, omitting then and using a newline is common style. Both produce the same behavior.

When no target value is given after case (the case ... when expression style), the construct behaves like if/elsif. This form is valid, but it can be confusing for readers, so if/elsif is often used for simple conditional branching while case/when is typically reserved for value matching.

Pattern matching (advanced structural decomposition matching available since Ruby 3.0) is a separate feature from case/when. For more on regular expression matching, see Regexp / match. For range objects, see Range / to_a / include? / cover?.

Common Mistakes

Writing comparison operators instead of expressions in a when clause

A when clause expects a value, a range, a regular expression, or a class name. Writing comparison operators such as > or < directly is a syntax error. To use comparison operators, either omit the target value after case (valueless case) or use if/elsif.

when_ng.rb
leap_count = 23

# Writing a comparison operator in when causes a syntax error
result = case leap_count
         when > 20 then "Almost at world line convergence"
         when > 10 then "Mid-stage time leaps"
         else           "Early stage"
         end
puts result
ruby when_ng.rb
when_ng.rb:4: syntax error, unexpected '>'

After fix:

when_ok.rb
leap_count = 23

# Use a Range object, or write it as if/elsif
result = case leap_count
         when 21..Float::INFINITY then "Almost at world line convergence"
         when 11..20              then "Mid-stage time leaps"
         else                          "Early stage"
         end
puts result
ruby when_ok.rb
Almost at world line convergence

Confusing the in operator with a range in when

The case/in construct (pattern matching since Ruby 2.7) is a different syntax from case/when. When using ranges in case/when, pass the Range object directly to when as when 1..10. Guard conditions like when x if x > 0 belong to the case/in syntax.

range_ng.rb
lab_number = 4

# Using in inside case/when is a syntax error
result = case lab_number
         when 1..5 in :founder then "Founding member"
         else "Later member"
         end
ruby range_ng.rb
range_ng.rb:6: syntax error, unexpected 'in'

After fix:

range_ok.rb
lab_number = 4

# In case/when, pass a Range object directly to when
result = case lab_number
         when 1..3  then "Founding member"
         when 4..10 then "Early member"
         else            "Later member"
         end
puts "Lab member ##{lab_number}: #{result}"
ruby range_ok.rb
Lab member #4: Early member

Trying to write multiple actions in an inline then clause

The one-line style using then is intended for a single expression. While multiple statements can technically be separated by semicolons after then, this hurts readability. When a when clause requires multiple actions, omitting then and using a newline is the common style.

then_ng.rb
okabe_status = "IBN5100 found"

# Chaining multiple actions with semicolons after then is hard to read
case okabe_status
when "IBN5100 found" then puts "Faris!"; puts "It's in Akihabara!"; puts "We need to get it"
when "Time machine complete" then puts "It's done!"
end

After fix:

then_ok.rb
okabe_status = "IBN5100 found"

# When multiple actions follow, omit then and use newlines
case okabe_status
when "IBN5100 found"
  puts "Faris!"
  puts "It's in Akihabara!"
  puts "We need to get it"
when "Time machine complete"
  puts "It's done!"
end
ruby then_ok.rb
Faris!
It's in Akihabara!
We need to get it

If you find any errors or copyright issues, please .