Question

Ruby Question Mark Methods: Predicate Methods Explained

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.”

Take Quiz

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:

  1. !@name.empty? checks that the name is not empty.
  2. @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:

  1. Product.new(0) creates a product whose @price is 0.
  2. Ruby reaches product.valid?.
  3. The valid? method evaluates @price > 0.
  4. 0 > 0 is false.
  5. The if condition receives false, so Ruby skips the first branch.
  6. Ruby runs the else branch and prints Cannot 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
Take Quiz

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

FormPurposeExample
valid?A predicate method name; conventionally returns true or falseproduct.valid?
!valid?Negates a predicate result!product.valid?
unless valid?Runs code when the predicate is falseunless product.valid?
condition ? a : bTernary conditional expressionproduct.valid? ? "yes" : "no"
valid!A method name ending in !; conventionally indicates a more dangerous or mutating versionrecord.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.

Take Quiz

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 true or false.

  • 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?, and positive?.

  • Do not write == true unless you specifically need to distinguish true from 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?.

Take Quiz

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.

Take Quiz

Keep learning

Related questions

View more