CrackedRuby logo

CrackedRuby

if/elsif/else Statements

Overview

Ruby implements conditional logic through if, elsif, and else statements that evaluate expressions and execute code blocks based on truthiness. Ruby considers all values truthy except false and nil. The conditional system supports multiple branching paths, modifier syntax, ternary operators, and case statements for complex decision-making scenarios.

Ruby's conditional statements return values, making them expressions rather than just control flow statements. The last evaluated expression in the executed branch becomes the return value of the entire conditional construct.

# Basic conditional structure
result = if temperature > 30
  "hot"
elsif temperature > 20
  "warm"
else
  "cool"
end
# => "warm" (if temperature is 25)

# Truthiness evaluation
if user && user.active?
  process_user(user)
end

# Single-line modifier syntax
return "invalid" if input.nil?

Basic Usage

The if statement evaluates a condition and executes the associated code block when the condition is truthy. Ruby supports both multiline and modifier forms of conditionals.

# Standard if statement
if user.authenticated?
  redirect_to dashboard_path
end

# if/else branching
if file.exists?
  content = file.read
else
  content = "default content"
end

# Multiple conditions with elsif
if score >= 90
  grade = "A"
elsif score >= 80
  grade = "B"
elsif score >= 70
  grade = "C"
else
  grade = "F"
end

The modifier syntax places the condition after the statement, creating more concise code for simple conditionals:

# Modifier if
puts "Processing..." if debug_mode

# Modifier unless (opposite of if)
raise ArgumentError unless params.valid?

# Assignment with modifier
total = calculate_sum if items.any?

Logical operators combine multiple conditions within a single if statement:

# AND operator
if user.admin? && feature_enabled?
  show_admin_panel
end

# OR operator
if weekend? || holiday?
  office_closed = true
end

# Complex logical expressions
if (user.premium? || user.trial_active?) && !user.suspended?
  grant_access
end

Advanced Usage

Ruby conditionals support complex nested structures, pattern matching with case statements, and functional programming patterns through conditional assignment and chaining.

# Nested conditionals with complex logic
def process_payment(amount, user, payment_method)
  if amount > 0
    if user.verified?
      if payment_method.valid?
        if payment_method.type == "credit_card"
          if payment_method.expires_at > Date.current
            charge_credit_card(amount, payment_method)
          else
            { error: "Expired card" }
          end
        elsif payment_method.type == "bank_transfer"
          initiate_bank_transfer(amount, payment_method)
        else
          { error: "Unsupported payment method" }
        end
      else
        { error: "Invalid payment method" }
      end
    else
      { error: "User not verified" }
    end
  else
    { error: "Invalid amount" }
  end
end

Case statements provide cleaner alternatives to long elsif chains:

# Case statement with value matching
def handle_response_code(code)
  case code
  when 200..299
    process_success
  when 300..399
    handle_redirect
  when 400..499
    log_client_error
  when 500..599
    alert_server_error
  else
    log_unknown_error
  end
end

# Case with type matching
def process_data(input)
  case input
  when String
    parse_string(input)
  when Array
    input.map { |item| process_data(item) }
  when Hash
    input.transform_values { |value| process_data(value) }
  when NilClass
    default_value
  else
    raise TypeError, "Unsupported type: #{input.class}"
  end
end

Conditional assignment operators provide concise ways to set values:

# OR-equals assignment (only assigns if left side is falsy)
@user ||= find_user_by_id(session[:user_id])
@cache ||= {}

# Conditional assignment with complex expressions
config[:database_url] ||= begin
  if Rails.env.production?
    ENV.fetch('DATABASE_URL')
  else
    "sqlite3:#{Rails.root}/db/development.sqlite3"
  end
end

# Ternary operator for inline conditionals
status = user.active? ? "online" : "offline"
message = errors.any? ? "Please fix errors" : "Form submitted successfully"

Common Pitfalls

Ruby's truthiness rules and conditional behavior can lead to unexpected results when developers assume behavior from other languages or misunderstand Ruby's evaluation patterns.

Truthiness Confusion: Only false and nil are falsy in Ruby, unlike languages where empty strings, zero, or empty arrays are falsy:

# Common mistake - these are all truthy in Ruby
if ""
  puts "Empty string is truthy in Ruby"  # This executes
end

if 0
  puts "Zero is truthy in Ruby"  # This executes
end

if []
  puts "Empty array is truthy in Ruby"  # This executes
end

# Correct way to check for empty values
if string && !string.empty?
  process_string(string)
end

if array && array.any?
  process_array(array)
end

Assignment vs. Comparison: Single = performs assignment and returns the assigned value, which can lead to bugs when == was intended:

# Bug - assignment instead of comparison
if user = find_admin_user  # Always truthy if find_admin_user returns anything
  grant_admin_access
end

# Correct comparison
if user == find_admin_user
  grant_admin_access
end

# Intentional assignment with explicit truthiness check
if (user = find_admin_user) && user.active?
  grant_admin_access
end

Case Statement Fallthrough: Ruby case statements don't fall through like switch statements in other languages, but multiple values can match a single when clause:

# Each when clause is independent - no fallthrough
case status
when "pending"
  queue_for_processing
when "approved"
  send_approval_email
  # Execution stops here, doesn't continue to next when
when "rejected"
  send_rejection_email
end

# Multiple values in single when clause
case day_of_week
when "saturday", "sunday"
  weekend_mode = true
when "monday", "tuesday", "wednesday", "thursday", "friday"
  weekend_mode = false
end

Nested Conditional Complexity: Deep nesting creates maintenance issues and can be refactored using guard clauses:

# Problematic deep nesting
def process_order(order)
  if order
    if order.valid?
      if order.items.any?
        if order.user.verified?
          if order.payment_method.present?
            process_payment(order)
          else
            { error: "No payment method" }
          end
        else
          { error: "User not verified" }
        end
      else
        { error: "No items in order" }
      end
    else
      { error: "Invalid order" }
    end
  else
    { error: "Order not found" }
  end
end

# Refactored with guard clauses
def process_order(order)
  return { error: "Order not found" } unless order
  return { error: "Invalid order" } unless order.valid?
  return { error: "No items in order" } unless order.items.any?
  return { error: "User not verified" } unless order.user.verified?
  return { error: "No payment method" } unless order.payment_method.present?

  process_payment(order)
end

Reference

Conditional Statement Syntax

Construct Syntax Returns Description
if if condition; code; end Last evaluated expression Executes code when condition is truthy
if/else if condition; code1; else; code2; end Last evaluated expression from executed branch Executes code1 or code2 based on condition
if/elsif/else if cond1; code1; elsif cond2; code2; else; code3; end Last evaluated expression from executed branch Multiple conditional branches
unless unless condition; code; end Last evaluated expression Executes code when condition is falsy
case/when case value; when match; code; end Last evaluated expression from matched branch Pattern matching against value

Modifier Forms

Modifier Syntax Description
if statement if condition Executes statement when condition is truthy
unless statement unless condition Executes statement when condition is falsy

Logical Operators

Operator Name Precedence Short-circuit Description
&& AND High Yes Returns first falsy value or last value
|| OR High Yes Returns first truthy value or last value
and AND Low Yes Same as && but lower precedence
or OR Low Yes Same as || but lower precedence
! NOT Highest No Returns opposite truthiness
not NOT Low No Same as ! but lower precedence

Truthiness Values

Value Truthiness Notes
true Truthy Boolean true
false Falsy Boolean false
nil Falsy Ruby's null value
0 Truthy Unlike many languages
"" Truthy Empty string is truthy
[] Truthy Empty array is truthy
{} Truthy Empty hash is truthy
All other objects Truthy Including custom objects

Assignment Operators

Operator Equivalent Description
||= x = x || y Assigns only if left side is falsy
&&= x = x && y Assigns only if left side is truthy
+= x = x + y Addition assignment
-= x = x - y Subtraction assignment

Case Statement Patterns

Pattern Example Description
Value equality when 1, 2, 3 Matches specific values
Range matching when 1..10 Matches values in range
Class matching when String Matches object type
Regex matching when /pattern/ Matches against regular expression
Proc matching when proc Calls proc with case value