Question
In Ruby, I know that writing:
some_objects.each(&:foo)
is commonly used as a shorter form of:
some_objects.each { |obj| obj.foo }
My understanding is that &:foo somehow creates a block like { |obj| obj.foo }, converts it to a Proc, and passes it to each.
Why does this work in Ruby? Is &:foo just a special language shortcut, or is there a deeper reason in the language for why it behaves this way?
Short Answer
By the end of this page, you will understand how Ruby's & operator works with blocks, how a Symbol like :foo becomes a callable object through to_proc, and why some_objects.map(&:name) is a real language feature rather than a random special case. You will also see when this shortcut is helpful and when a normal block is clearer.
Concept
In Ruby, the &:method_name pattern is based on two language features working together:
&in a method call means: convert this object into a block.Symbol#to_proclets a symbol such as:footurn into aProc.
So when Ruby sees this:
some_objects.each(&:foo)
it roughly interprets it like this:
some_objects.each(&(:foo.to_proc))
And :foo.to_proc produces a proc that calls foo on whatever object it receives.
Conceptually, it behaves like:
proc { |obj| obj.foo }
That is why it works with iterator methods such as each, map, select, and similar methods that accept blocks.
Why this matters
Mental Model
Think of & as a block adapter.
A method like each wants a block. But instead of giving it a normal block directly, you hand Ruby an object.
some_objects.each(&:foo)
Ruby says:
- “I need a block here.”
- “You gave me
:foowith an&.” - “Let me ask
:footo turn itself into a proc by callingto_proc.” - “Now I can use that proc as the block.”
A symbol like :foo is therefore acting like a label for a method name. Ruby converts that label into a callable block that says:
- “When I receive an object, call
fooon it.”
So you can imagine &:foo as a little remote control button labeled foo. Each object in the collection gets the same button pressed on it.
Syntax and Examples
Core syntax
collection.map(&:method_name)
This is shorthand for:
collection.map { |item| item.method_name }
Example 1: Extract names
users = [
OpenStruct.new(name: "Ava"),
OpenStruct.new(name: "Ben"),
OpenStruct.new(name: "Cara")
]
names = users.map(&:name)
puts names.inspect
Output:
["Ava", "Ben", "Cara"]
Explanation:
maploops through each user&:namebecomes a proc- that proc calls
nameon each user mapcollects the returned names into a new array
Example 2: Convert strings to integers
Step by Step Execution
Consider this code:
words = ["cat", "dog", "bird"]
lengths = words.map(&:length)
puts lengths.inspect
Here is what happens step by step:
wordsis an array containing three strings.mapstarts iterating through each element.- Ruby sees
&:lengthand knowsmapexpects a block. - Ruby calls
to_procon:length. - That creates a proc that behaves roughly like:
proc { |item| item.length }
mapcalls that proc for each item:- for
"cat"→"cat".length→3 - for
"dog"→"dog".length→3
- for
Real World Use Cases
Common places you will see &:symbol
Transforming arrays
products.map(&:price)
orders.map(&:id)
messages.map(&:strip)
Used when you want one property or one method result from every object.
Cleaning input data
params[:tags].map(&:strip).reject(&:empty?)
Useful for removing extra spaces and blank values.
Working with API or database results
users.map(&:email)
records.map(&:attributes)
Developers often extract fields from collections of model objects.
Type conversion
csv_row.map(&:to_s)
values.map(&:to_i)
Helpful when normalizing incoming data.
Boolean-style filtering
items.select(&:valid?)
This keeps only items for which valid? returns true.
Real Codebase Usage
In real Ruby projects, &:symbol appears most often in collection pipelines.
Common patterns
Simple mapping
user_names = users.map(&:name)
Validation and filtering
valid_orders = orders.select(&:valid?)
Cleanup chains
tags = raw_tags.map(&:strip).reject(&:empty?).uniq
Guarding readability
Developers often avoid &:symbol if the expression becomes harder to understand.
# Clear
users.map(&:name)
# Often clearer as a block
users.map { |user| user.profile.display_name }
How it relates to other Ruby patterns
- Guard clauses: not directly related, but both aim to keep code concise and readable.
- Validation:
select(&:valid?)is common when filtering objects by a predicate method. - Error handling: if some objects may not respond to the method, developers usually avoid unless they are sure the method exists.
Common Mistakes
1. Thinking &:foo is magic syntax only for symbols
It is not a one-off exception. & means “convert this object to a proc for use as a block.” Symbols work because Symbol defines to_proc.
2. Using it when the method needs extra logic
Broken for readability:
users.map(&:name.downcase)
This does not mean “call name.downcase on each user.”
Write this instead:
users.map { |user| user.name.downcase }
3. Using it on objects that do not respond to the method
items = ["a", 1, nil]
items.map(&:upcase)
This will fail because 1 and nil do not have upcase.
Safer alternative:
items.filter_map { || item.upcase item.respond_to?() }
Comparisons
&:symbol vs explicit block
| Style | Example | Best when | Notes |
|---|---|---|---|
&:symbol | users.map(&:name) | One simple method call | Very concise |
| Explicit block | `users.map { | u | u.name }` |
map(&:foo) vs each(&:foo)
| Method | Purpose | Return value |
|---|---|---|
map(&:foo) | Transform each element into a new value |
Cheat Sheet
Quick reference
Basic form
collection.map(&:method_name)
Equivalent to:
collection.map { |item| item.method_name }
Why it works
&tells Ruby to treat something as a block- Ruby calls
to_procon the object after& Symbol#to_procturns:nameinto a proc that callsname
Common examples
users.map(&:name)
strings.map(&:upcase)
values.map(&:to_i)
orders.select(&:paid?)
Good use cases
- one short method call per item
- readable collection transformations
- simple predicate filtering
Avoid when
- you need chained logic like
user.name.downcase - you need conditionals
FAQ
What does &:name mean in Ruby?
It means Ruby converts the symbol :name into a proc and uses it as the block. In practice, it calls name on each item.
Is &:symbol exactly the same as { |x| x.foo }?
For common usage, yes, that is the right mental model. Internally, Ruby uses Symbol#to_proc to create the proc.
Why does the ampersand work here?
In a method call, & tells Ruby to convert an object into a block by calling to_proc on it.
Is this only for symbols?
No. Any object that implements to_proc can be used with & in a method call.
When should I avoid &:symbol?
Avoid it when the logic is more than one simple method call, or when the shorter syntax makes the code harder to read.
Does each(&:foo) return the results of foo?
Usually no. each typically returns the original collection. If you want collected results, use .
Mini Project
Description
Build a small Ruby script that processes a list of users and demonstrates when &:symbol is useful. This project shows how to extract values, filter records, and compare the shortcut with explicit blocks in a realistic collection-processing task.
Goal
Create a script that reads an array of user objects, prints all names, keeps only active users, and formats email addresses in lowercase.
Requirements
- Define a simple
Userclass withname,email, andactiveattributes. - Create an array with at least four user objects.
- Use
map(&:name)to collect user names. - Use a predicate method with
selectto keep only active users. - Use an explicit block for a transformation that needs more than one method call.
Keep learning
Related questions
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.
Convert a Unix Timestamp to Ruby DateTime
Learn how to convert Unix timestamps to Ruby DateTime and Time objects, with examples, differences, pitfalls, and practical Ruby usage.