Array#detect
arr.detect { |element| block } -> obj or nil .detect is an alias for .find. It iterates through an array or enumerable and returns the first element for which the block evaluates to truthy. If no element matches, it returns nil.
Syntax
array.detect { |element| block } -> obj or nil
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
block | Proc | Required | A block that receives each element and returns truthy for matching elements |
The method walks the array in order and stops at the first truthy block result. Because it short-circuits, detect is efficient for large collections where the match is likely to appear early. The return value is the element itself, not a boolean, so the caller can use it directly.
Examples
Basic usage
numbers = [1, 3, 5, 7, 9]
numbers.detect { |n| n > 4 }
# => 5
numbers.detect { |n| n > 10 }
# => nil
When the array contains hashes instead of simple values, the block naturally targets a specific key. The return value is the entire hash, not just the matching value, so the caller gets the full record back. This makes detect a clean fit for lookup tables and search results where the matching row is the real prize.
Finding a hash in an array
users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 35 }
]
users.detect { |user| user[:age] > 28 }
# => { name: "Alice", age: 30 }
detect works the same way on arrays of strings as it does on arrays of numbers or hashes. The block receives each string in order, and the first one that satisfies the condition is returned. This consistency across types is part of what makes the method easy to reach for in ad-hoc searches.
Using with strings
words = ["apple", "banana", "cherry", "date"]
words.detect { |word| word.start_with?("b") }
# => "banana"
words.detect { |word| word.length > 10 }
# => nil
When the search target is an array of hashes or objects, the block grows to match the data shape but the overall pattern stays the same. Each element is tested against a predicate, and the first match is returned. The method does not change whether the array holds simple values or structured records.
Common Patterns
Finding by attribute
products = [
{ id: 1, name: "Widget", price: 100 },
{ id: 2, name: "Gadget", price: 50 },
{ id: 3, name: "Gizmo", price: 75 }
]
# Find product by ID
products.detect { |p| p[:id] == 2 }
# => { id: 2, name: "Gadget", price: 50 }
Because detect returns nil when nothing matches, the caller can chain a fallback with || to supply a default. This pattern is especially clean when the search array might be empty or when the matching criteria are strict enough that a miss is expected in normal operation.
Safe navigation with detect
results = []
found = results.detect { |x| x > 5 }
# Returns nil safely, no error
# Common pattern: use || with default value
found = results.detect { |x| x > 5 } || "no match"
# => "no match"
The fallback pattern with || works well in practice because nil is falsy in Ruby. If the search succeeds, the returned value replaces the entire expression. If it fails, the right side of || fills in. This single-line idiom is compact enough to use inline in assignments and method arguments without cluttering the surrounding code.
Use detect for the first match
detect is a good fit when you want the first matching element and nothing more. It reads naturally in arrays and other enumerable objects because the block acts like a small search rule: keep going until the condition succeeds, then return that value. That makes the method useful for lookup-style code where the data is already in a list and the matching item is the real target. The return value is the item itself, not a boolean, so the next line can use it directly.
Keep the search rule simple
The block passed to detect should usually be short and easy to scan. That is especially true when the array contains hashes, strings, or objects with a clear property you want to test. A compact search rule keeps the code easy to understand, and it makes the point of the iteration obvious. If the condition grows too large, it can help to move part of the logic into a helper method so the call site stays focused on the search itself.
Lean on nil when nothing matches
One of the method’s nicest properties is that it returns nil when the search fails. That means the caller can branch, fall back, or chain a default without needing special handling for an exception. The pattern is common in Ruby because it keeps search code calm and predictable. When you are scanning arrays or other enumerables for the first useful value, detect gives you a clear result and a clear signal when the result does not exist.