Question

What `map(&:name)` Means in Ruby

rubysyntaxoperatorsparameter-passing

Question

I found the following Ruby code in a RailsCast and want to understand what this part means: map(&:name).

def tag_names
  @tag_names || tags.map(&:name).join(' ')
end

What does (&:name) do when used with map in Ruby?

Short Answer

By the end of this page, you will understand why map(&:name) is a short Ruby way to call the name method on every item in a collection. You will also learn how the & operator and symbols work together, how this compares to a normal block, and when this shorthand is useful in real Ruby and Rails code.

Concept

In Ruby, map loops through a collection and returns a new array containing the result of running something on each element.

For example:

[1, 2, 3].map { |n| n * 2 }
# => [2, 4, 6]

When you write:

tags.map(&:name)

Ruby is using a shorthand for a very common pattern:

tags.map { |tag| tag.name }

What the pieces mean

  • :name is a symbol representing the method name name
  • & tells Ruby to convert that symbol into something usable as a block
  • map then calls that method on each element

So if tags is a collection of tag objects, map(&:name) means:

  • take each tag
  • call tag.name
  • collect the results into a new array

Why this matters

This syntax appears often in Ruby and Rails because it makes code shorter and easier to scan when you just want to call a single method on every item in a collection.

In your example:

def tag_names
  @tag_names || tags.map(&:name).join(' ')
end

the code:

  1. gets all tags
  2. extracts each tag's name
  3. joins those names with spaces

If the tag names were "ruby", "rails", and "api", the result would be:

"ruby rails api"

Under the hood

Ruby supports this because Symbol can be converted into a callable object using to_proc.

So this:

&:name

is roughly like:

{ |object| object.name }

You do not usually need to call to_proc yourself, but it helps explain why the syntax works.

Mental Model

Think of map as a worker on an assembly line.

  • The collection is a line of items moving past
  • map applies the same action to each item
  • &:name is like giving the worker a small instruction card that says: for each item, ask for its name

So instead of saying:

map { |item| item.name }

you hand Ruby a shortcut card:

map(&:name)

Same job, shorter instruction.

Take Quiz

Syntax and Examples

Basic 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: "Liam"),
  OpenStruct.new(name: "Noah")
]

users.map(&:name)
# => ["Ava", "Liam", "Noah"]

This calls name on each user object.

Example 2: Convert strings to uppercase

words = ["ruby", "rails", "api"]
words.map(&:upcase)
# => ["RUBY", "RAILS", "API"]

This calls upcase on each string.

Example 3: Compare with block syntax

tags.map(&:name)

is equivalent to:

tags.map { |tag| tag.name }

In your Rails example

def tag_names
  @tag_names || tags.map(&:name).join(' ')
end

Explanation:

  • tags.map(&:name) returns an array of names
  • .join(' ') combines them into one string separated by spaces
  • @tag_names || ... returns @tag_names if it already exists, otherwise it builds the string from tags

Example:

tags.map(&:name)
# => ["ruby", "rails", "testing"]

tags.map(&:name).join(' ')
# => "ruby rails testing"

Step by Step Execution

Consider this code:

words = ["ruby", "rails", "api"]
result = words.map(&:upcase)

Here is what happens step by step:

  1. words is an array with three strings:

    • "ruby"
    • "rails"
    • "api"
  2. map starts looping through the array.

  3. &:upcase tells Ruby: for each element, call the upcase method.

  4. Ruby processes each item:

    • "ruby".upcase → "RUBY"
    • "rails".upcase → "RAILS"
    • "api".upcase → "API"
  5. map collects the results into a new array.

  6. result becomes:

["RUBY", "RAILS", "API"]

Now trace your original example:

def tag_names
  @tag_names || tags.map(&:name).join(' ')
end

If @tag_names is nil and tags contains tag objects with names "ruby" and "rails", then:

  1. @tag_names is checked
  2. because it is nil, Ruby evaluates the right side of ||
  3. tags.map(&:name) becomes tags.map { |tag| tag.name }
  4. Ruby builds ["ruby", "rails"]
  5. .join(' ') turns that into "ruby rails"
  6. the method returns "ruby rails"

Real World Use Cases

map(&:method_name) is common when you want one value from each object in a collection.

Common practical uses

  • Rails views: get names or titles for display

    @posts.map(&:title)
    
  • Building API responses: extract IDs or fields

    users.map(&:id)
    
  • Data cleanup: transform strings

    emails.map(&:downcase)
    
  • Admin dashboards: list labels from objects

    categories.map(&:name)
    
  • Form helpers: prepare selected values

    roles.map(&:name).join(", ")
    

Why developers like it

  • short and readable for simple method calls
  • avoids unnecessary block variables
  • works well in chains with map, select, and join
Take Quiz

Real Codebase Usage

In real Ruby and Rails projects, this shorthand is often used when the block only calls one method with no extra logic.

Typical patterns

Extracting attributes

user_ids = users.map(&:id)
post_titles = posts.map(&:title)

Preparing display strings

tag_list = tags.map(&:name).join(", ")

Working with associations in Rails

@article.comments.map(&:body)
@order.line_items.map(&:price)

Combining with other enumerable methods

users.select(&:active?).map(&:email)

This means:

  1. keep only active users
  2. get each user's email

When developers avoid it

If the logic is more than a simple method call, a normal block is usually clearer:

users.map { |user| "#{user.first_name} #{user.last_name}" }

That is better than forcing shorthand where it does not fit.

Readability guideline

Use &:method_name when:

  • you are calling exactly one method
  • the intent is obvious
  • the shorter form improves readability

Use a block when:

  • you need multiple operations
  • you need conditions
  • you need arguments
  • the shorthand would hide what the code is doing

Common Mistakes

1. Thinking &:name is special syntax only for map

It is not limited to map. It can be used with other methods that accept a block, such as select, reject, and any?.

users.select(&:active?)

2. Using it when the method needs arguments

This does not work for methods that require extra arguments in this form.

Broken example:

words.map(&:gsub)

Why it fails:

  • gsub needs arguments
  • &:gsub only says "call gsub"
  • it does not provide the required parameters

Use a block instead:

words.map { |word| word.gsub("a", "@") }

3. Using it when the method may not exist

Broken example:

items.map(&:name)

If some items do not respond to name, Ruby raises an error.

Avoid this by ensuring all objects support the method, or use safer logic.

4. Assuming it is always more readable

Sometimes the long form is clearer:

orders.map { |order| order.total_price.round(2) }

Trying to force shorthand here would not help.

5. Confusing symbols with strings

: creates a symbol, not a string.

:name   # symbol
"name" # string

&:name works with a symbol because Ruby can convert it to a proc.

6. Forgetting that map returns a new array

map does not change the original collection unless you use map!.

names = ["ruby", "rails"]
upper = names.map(&:upcase)

# names is still ["ruby", "rails"]
# upper is ["RUBY", "RAILS"]

Comparisons

map(&:name) vs block syntax

StyleExampleBest for
Shorthandtags.map(&:name)Simple single method calls
Block`tags.map {tag
Block with logic`tags.map {tag

map vs each

MethodReturnsUse when
mapA new transformed arrayYou want changed values
eachThe original collectionYou want side effects, like printing or saving

Example:

names = users.map(&:name)
users.each { |user| puts user.name }

map(&:name) vs pluck(:name) in Rails

ApproachWorks onNotes
map(&:name)Ruby objects already loaded in memoryCalls name on each object
pluck(:name)ActiveRecord queryFetches only that column from the database

Example:

User.all.map(&:name)
User.pluck(:name)

In Rails, pluck can be more efficient when you only need database column values.

&:method vs explicit proc

StyleExampleMeaning
Symbol shorthanditems.map(&:name)Convert symbol to proc automatically
Explicit procitems.map(&:method(:name))Different and less common here
Normal block`items.map {i
Take Quiz

Cheat Sheet

Quick reference

Basic form

collection.map(&:method_name)

Equivalent to:

collection.map { |item| item.method_name }

Common examples

users.map(&:name)
posts.map(&:title)
words.map(&:upcase)
users.select(&:active?)

What & does

  • converts an object into a block if possible
  • with symbols, Ruby uses to_proc

What :name is

  • a symbol representing the method name name

Good use cases

  • calling one method on each element
  • short, clear collection transformations

Avoid when

  • the method needs arguments
  • you need multiple steps
  • the shorthand hurts readability

Related equivalent

items.map(&:name)
items.map { |item| item.name }

Important note

map returns a new array. It does not modify the original collection unless you use map!.

FAQ

What does map(&:name) mean in Ruby?

It means: loop through the collection, call name on each item, and return the results in a new array.

Is map(&:name) the same as map { |x| x.name }?

Yes. For this case, they are equivalent.

What does the & do in &:name?

It tells Ruby to convert the symbol into a block-like callable object.

Why is a symbol used instead of a string?

Ruby supports converting symbols like :name into procs for this shorthand. Strings do not work the same way here.

Can I use &:name with methods other than map?

Yes. Any method that accepts a block may be able to use this style, such as select, reject, or any?.

Does map(&:name) work if the method takes arguments?

Usually no. If arguments are needed, use a normal block.

Is map(&:name) always better than a block?

No. It is best for simple single-method calls. A regular block is often clearer when logic is more complex.

In Rails, should I use map(&:name) or pluck(:name)?

If records are already loaded, map(&:name) is fine. If you only need a database column, pluck(:name) is often more efficient.

Take Quiz

Mini Project

Description

Build a small Ruby script that works with a list of objects and uses map(&:method_name) to extract data. This helps you practice the shorthand in a realistic way, similar to how Rails apps collect names, titles, or IDs from model objects.

Goal

Create a script that stores several book objects, extracts their titles with map(&:title), and prints them as a single formatted string.

Requirements

  • Define a Book class with a title attribute.
  • Create at least three Book objects.
  • Store the books in an array.
  • Use map(&:title) to extract all titles.
  • Join the titles into one string and print the result.
Take Quiz

Keep learning

Related questions

View more