Enumerable#take
The take method returns the first n elements from an enumerable. It is useful for previewing a collection, limiting the number of results, or splitting a collection into head and tail parts alongside its counterpart, drop.
How it works
collection.take(n)
take(n) collects the first n elements from the beginning of the collection and returns them as a new array. If the collection has fewer than n elements, take returns all of them — it never raises an error.
Unlike first, which is defined only on Array and returns nil when called without arguments on an empty collection, take works across all enumerable types and always returns an array, making it the safer choice for generic collection code.
Basic Usage
Get the first 3 elements from an array:
[10, 20, 30, 40, 50].take(3)
# => [10, 20, 30]
Calling take(3) on an array of five elements returns the first three as a new array. The original collection is not modified, and the result is a plain Array regardless of the source type. This makes take predictable: you always know you are getting back an array.
Works with any enumerable, including ranges:
(1..10).take(4)
# => [1, 2, 3, 4]
Ranges are enumerable, so take works on them without any conversion. The method collects the first four elements from the range and returns them as an array, which is often more convenient than manually slicing or converting the range to an array first.
And with lazily evaluated enumerables:
[1, 2, 3, 4, 5].lazy.take(2).to_a
# => [1, 2]
When combined with a lazy enumerator, take limits evaluation to only the first n elements before forcing with to_a. This is particularly useful when the source collection is large or expensive to traverse, since it avoids processing elements beyond the ones you actually need.
When n exceeds collection size
take is forgiving — if n is larger than the number of elements available, it simply returns everything:
[1, 2, 3].take(10)
# => [1, 2, 3]
{ a: 1, b: 2 }.take(10)
# => [[:a, 1], [:b, 2]]
This behaviour makes take safe to use without checking the collection size beforehand.
take vs first
take(n) and first are related but differ in important ways:
| Method | Type | Arguments | Return on empty collection |
|---|---|---|---|
take(n) | Enumerable | Accepts an integer n | Empty array [] |
first | Array | Optional integer n (defaults to 1) | nil or [] depending on argument |
first is defined on Array directly and raises an error when called on an empty collection without arguments. take is defined on Enumerable and works consistently across any enumerable type:
# first is an Array method
[1, 2, 3].first(2)
# => [1, 2]
# first without argument on empty array returns nil
[].first
# => nil
# take is Enumerable — works on any enumerable
(1..0).take(3)
# => []
Set.new.take(2)
# => [#<Set: {}>] — note: Set doesn't preserve order in older Ruby
For most practical cases where you want the first n elements from a collection of unknown type, take is the safer choice.
Practical Examples
Preview Data
When working with large datasets, use take to peek at the first few records. This approach is useful in Rails consoles, data exploration scripts, and anywhere you want to inspect the shape of the data without printing hundreds of rows to the screen:
users = User.all.order(created_at: :desc)
puts "Latest users:"
users.take(5).each { |u| puts " #{u.name}" }
Previewing the first few records with take is a lightweight alternative to pagination when you only need a quick sense of what the data looks like. It avoids loading the entire collection into memory for rendering and keeps the output manageable in interactive environments like IRB or a Rails console, where printing hundreds of rows would clutter the session.
Limit Results
Combine take with other Enumerable methods to build query-like behaviour:
results = [3, 1, 4, 1, 5, 9, 2, 6].select(&:odd?).take(3)
# => [3, 1, 5]
Chaining select with take produces a limited set of filtered results in one expression. The select narrows the collection to matches, and take caps the result count, which is a common pattern for query-style pipelines where you want the first few items that satisfy a condition without processing the entire collection.
Head and Tail with drop
Pair take with drop to split a collection into the first n elements and the remainder:
numbers = (1..10).to_a
head = numbers.take(3)
tail = numbers.drop(3)
puts "Head: #{head.inspect}" # => [1, 2, 3]
puts "Tail: #{tail.inspect}" # => [4, 5, 6, 7, 8, 9, 10]
This pattern avoids calling first and last on the same array, which can be clearer in functional-style code. Splitting a collection into head and tail also makes it easy to process the first few items differently from the rest, such as rendering a featured section followed by a full list. The split is clean and the intent stays obvious even when the collection is large.
Paginated API Responses
Simulate fetching paginated data from an API:
all_items = (1..100).to_a
page_size = 10
page_number = 3
offset = (page_number - 1) * page_size
page = all_items.drop(offset).take(page_size)
# => [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
See Also
- /reference/enumerable/enumerable-drop/ — skip the first n elements
- /reference/enumerable/enumerable-each-slice/ — group elements into fixed-size chunks
- /reference/enumerable/enumerable-each-cons/ — iterate over consecutive overlapping groups