Question
What is the purpose of a question mark (?) at the end of a Ruby method name? For example, what does this code mean?
assert !product.valid?
Why are methods such as valid? often used in if statements and other conditional expressions?
Short Answer
By the end of this page, you will understand Ruby predicate methods: methods whose names end in ?. You will know why they are commonly used for checks such as valid?, how Ruby evaluates them in conditions, and how to write clear predicate methods of your own.
Concept
In Ruby, a question mark at the end of a method name usually indicates a predicate method: a method that answers a yes-or-no question.
product.valid?
user.admin?
file.exist?
The ? is part of the method's name. It is not an operator applied after calling valid.
By Ruby convention, predicate methods should return either true or false:
def adult?
age >= 18
end
This naming convention makes code read naturally:
if product.valid?
save_product(product)
end
Ruby does not strictly force a method ending in ? to return a Boolean value, but returning true or false is the expected and readable design. Other developers will assume that available?, empty?, and valid? are checks.
Predicate methods matter because they give conditionals meaningful names. Compare if product.valid? with if product.errors.empty?. Both can work, but a well-named predicate communicates the business rule directly.
Mental Model
Think of a predicate method as asking an object a question.
product.valid?asks: “Is this product valid?”cart.empty?asks: “Is this cart empty?”user.admin?asks: “Is this user an administrator?”
The object responds with true or false. An if statement uses that answer to decide which path to take.
The question mark is a label on the method name that tells readers: “This method is a question, so expect a yes-or-no answer.”
Syntax and Examples
Define a predicate method by placing ? at the end of its name.
class Product
def initialize(name, price)
@name = name
@price = price
end
def valid?
!@name.empty? && @price.positive?
end
end
product = Product.new("Notebook", 5)
puts product.valid? # true
valid? evaluates two conditions:
!@name.empty?checks that the name is not empty.@price.positive?checks that the price is greater than zero.
The && expression returns true only when both checks are true.
Use a predicate directly in a conditional:
if product.valid?
puts "Product can be saved"
else
puts "Product needs correction"
end
You can also negate its result with !:
puts "Invalid product" unless product.valid?
Here, ! is the logical NOT operator. It reverses the Boolean result returned by valid?.
Step by Step Execution
Consider this example:
class Product
def initialize(price)
@price = price
end
def valid?
@price > 0
end
end
product = Product.new(0)
if product.valid?
puts "Saved"
else
puts "Cannot save"
end
Step by step:
Product.new(0)creates a product whose@priceis0.- Ruby reaches
product.valid?. - The
valid?method evaluates@price > 0. 0 > 0isfalse.- The
ifcondition receivesfalse, so Ruby skips the first branch. - Ruby runs the
elsebranch and printsCannot save.
The question mark does not change the evaluation itself. It communicates that valid? is intended to return an answer suitable for a condition.
Real World Use Cases
Predicate methods appear throughout Ruby applications.
- Form and model validation:
order.valid?checks whether required data is present and acceptable before saving. - Authorization:
current_user.admin?decides whether to show an administration action. - Collections:
items.empty?checks whether there is anything to display. - Files and paths:
File.exist?(path)checks whether a file exists before reading it. - Feature settings:
config.cache_enabled?determines whether caching should run. - Business rules:
invoice.overdue?checks whether an invoice needs a reminder.
For example, an API endpoint might prevent an invalid record from being persisted:
if order.valid?
order.save
puts "Order created"
else
puts "Order is invalid"
end
Real Codebase Usage
In real codebases, predicate methods are often used to move a condition out of a long controller, service, or model method and give it a useful name.
Guard clauses
A guard clause exits early when a required condition is not met:
def send_receipt(order)
return unless order.paid?
ReceiptMailer.send(order)
end
paid? makes the rule obvious: do not send a receipt unless the order is paid.
Validation helpers
def eligible_for_discount?
active? && total_cents >= 5_000
end
The rest of the program does not need to know every detail of discount eligibility.
Filtering data
active_users = users.select(&:active?)
select keeps the users for which active? returns true.
Clear conditional branches
if response.success?
process_response(response)
else
log_failure(response)
end
Use predicate names that describe a state or question, such as published?, expired?, authorized?, and empty?.
Common Mistakes
Treating ? as a separate operator
In this code, ? belongs to the method name:
product.valid?
Ruby is not calling a method named valid and then applying an operator called ?.
Forgetting that ! reverses the result
assert !product.valid?
This asserts that product.valid? is false. It does not mean “assert the product is valid.”
A clearer equivalent is often:
refute product.valid?
when using Minitest.
Returning a non-Boolean value from a predicate
This runs, but it is misleading:
def premium?
@plan_name
end
A nonempty string is truthy in Ruby, but callers expect premium? to return true or false. Write:
def premium?
@plan_name == "premium"
end
Comparing a predicate to true
Avoid unnecessary comparisons:
# Unnecessary
if product.valid? == true
puts "Valid"
end
Use the predicate directly:
if product.valid?
puts "Valid"
end
Confusing predicate methods with the ternary conditional
Ruby also uses ? in a ternary expression:
message = product.valid? ? "Valid" : "Invalid"
The first ? belongs to valid?; the second ? is the ternary operator. Spacing helps make this easier to read.
Comparisons
| Form | Purpose | Example |
|---|---|---|
valid? | A predicate method name; conventionally returns true or false | product.valid? |
!valid? | Negates a predicate result | !product.valid? |
unless valid? | Runs code when the predicate is false | unless product.valid? |
condition ? a : b | Ternary conditional expression | product.valid? ? "yes" : "no" |
valid! | A method name ending in !; conventionally indicates a more dangerous or mutating version | record.save! |
A trailing ? and a trailing ! are both part of Ruby method names, but their conventions differ:
?means “this is a question/check.”!usually means “this version changes the receiver or raises an error,” depending on the API.
Unlike ?, a trailing ! does not inherently mean that a method returns false or true.
Cheat Sheet
-
A method ending in
?is called a predicate method. -
The
?is part of the method name:valid?is one method name. -
Predicate methods should normally return
trueorfalse. -
Use them directly in conditions:
if user.admin? grant_access end -
Negate a predicate with
!:return unless account.active? -
Common Ruby predicates include
empty?,nil?,include?,start_with?,valid?, andpositive?. -
Do not write
== trueunless you specifically need to distinguishtruefrom other truthy values. -
?can also appear in Ruby's ternary expression:condition ? value_if_true : value_if_false.
FAQ
Is the question mark required for a Boolean method in Ruby?
No. A method can return true or false without ending in ?. However, using ? is the standard Ruby convention when the method represents a yes-or-no check.
Does Ruby enforce that methods ending in ? return true or false?
No. Ruby allows any return value. Still, a predicate method should return a Boolean so its name matches its behavior.
What does assert !product.valid? mean?
It means the test expects product.valid? to be false. The ! negates the result.
Why can valid? be used directly in an if statement?
if evaluates an expression. If the expression is true or truthy, Ruby runs the first branch. Predicate methods are designed to provide such a condition.
What values are false in Ruby?
Only false and nil are falsey. Everything else, including 0, empty strings, and empty arrays, is truthy.
Is ? always part of a method name in Ruby?
No. Ruby also uses ? in ternary expressions, such as logged_in? ? dashboard : sign_in. In that example, logged_in? is a method name and the later ? is ternary syntax.
Can I create my own methods ending in ??
Yes. Use names that describe a state or condition, such as expired?, ready?, or eligible?.
Mini Project
Description
Create a small Subscription class that uses predicate methods to express common account states. This models the kind of checks an application performs before allowing access to paid content.
Goal
Determine whether a subscription can access premium content by combining clearly named predicate methods.
Requirements
Create a Subscription class that stores a plan name and an expiration date.
Add an active? method that returns whether the subscription has not expired.
Add a premium? method that returns whether the plan is "premium".
Add a can_access_premium? method that returns true only for active premium subscriptions.
Create two subscriptions and print their access results.
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.