Ruby and Keyword
last modified October 18, 2026
This tutorial explains how to use Ruby's and keyword. It serves
as both a logical operator and a control flow tool in Ruby programs.
The and keyword evaluates multiple expressions, returning the first
falsey value or the last truthy value. It has lower precedence than &&.
Unlike &&, and is useful for control flow rather than
boolean logic. It's commonly used for chaining operations where any failure
should stop execution.
Basic and Operator
This example shows the basic operation of and. It returns the last
operand when both are truthy, and the first falsey operand otherwise.
result = (true and false) puts result # => false result = (1 and "hello") puts result # => hello result = (nil and 5) puts result.inspect # => nil result = true and false puts result # => true
The and operator evaluates expressions left-to-right. It returns
the first falsey value or the last value if all are truthy. The parentheses in
the first three examples make the and expression evaluate before
assignment. Without them, = binds more tightly: the last line
assigns true to result, then evaluates
and false and discards that value.
and vs && Precedence
The key difference between and and && is precedence.
Both operators are left-associative, but and has much lower
precedence, which affects evaluation order.
x = true && false puts x # => false y = true and false puts y # => true
The first example assigns the result of && to x.
The second assigns true to y, then evaluates
and false. The and expression itself is false, but its
value is not assigned. This demonstrates and's lower precedence.
Control Flow with and
and is often used for control flow where operations should continue
only if previous ones succeed. This example shows a common pattern.
def fetch_data(success)
success ? "data" : nil
end
def process_data(data)
puts "Processing: #{data}"
end
data = fetch_data(true) and process_data(data)
puts "Data processed successfully" if data
data = fetch_data(false) and process_data(data)
puts "No data to process" unless data
The process_data method only runs if fetch_data
returns a truthy value. When it returns nil, and
short-circuits and the second call is skipped. The example prints
Processing: data, Data processed successfully, and
No data to process.
Multiple Conditions with and
and can chain multiple conditions together. Evaluation stops at the
first falsey value due to short-circuit behavior.
def valid_user?(user)
!!(user[:name] and user[:email] and user[:active])
end
user1 = { name: "John", email: "john@example.com", active: true }
user2 = { name: "Alice", email: nil, active: true }
puts valid_user?(user1) # => true
puts valid_user?(user2) # => false
The method checks all required user attributes. and returns the
first falsey operand, which is nil here, so the double negation
converts the result to true or false. Evaluation stops
at the first falsey value.
and for Assignment Guarding
and can guard a second assignment when a condition fails. The first
assignment still happens, but the second one is skipped, which avoids calling a
method on nil.
def get_config_value(found) found ? "admin" : nil end role = get_config_value(true) and role = role.upcase puts role.inspect # => "ADMIN" role = get_config_value(false) and role = role.upcase puts role.inspect # => nil
The first assignment always happens. The and operator guards only
the second assignment, so role is uppercased only when the lookup
succeeds. On failure, role is still assigned nil, which
prevents calling upcase on nil.
Guarding a Method Call with and
and can guard a method call, so the second call runs only when the
first one succeeds. This provides a concise alternative to a nested
if.
def authenticate(user)
user[:password] == "secret"
end
def log_in(user)
puts "Logging in #{user[:name]}"
user[:authenticated] = true
end
current_user = { name: "John", password: "secret" }
authenticate(current_user) and log_in(current_user) # prints "Logging in John"
The log_in method only executes if authenticate
returns true. This pattern is common in authentication flows. The methods must
be defined before the guarded call, because Ruby resolves method calls at
runtime.
Error Handling with and
and can chain operations with error handling. Each step executes
only if the previous one succeeds.
require 'json'
def parse_json(data)
JSON.parse(data) rescue nil
end
data = '{"name": "John"}' and config = parse_json(data)
puts config ? "Config loaded" : "Failed to load config" # prints "Config loaded"
data = 'not valid json' and config = parse_json(data)
puts config ? "Config loaded" : "Failed to load config" # prints "Failed to load config"
Each step proceeds only if the previous one succeeds. parse_json
returns nil for invalid input, so the second example prints
Failed to load config instead of raising an exception. Because
and has lower precedence than =, data is
assigned first and config receives the parsed result.
Source
This tutorial covered Ruby's and keyword with practical examples
showing boolean logic, control flow, and error handling patterns.
Author
List all Ruby tutorials.