And &, per se.
Tags: ruby, programming, tutorial
Published: 2020-11-12 06:12:35

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ghgukwmgc23zk3s6zgq5.jpg)

This blog will cover three common uses that will help clarify the purpose and application of the & operator.

- Convert a variable into a proc
- Shorten array enumerables
- Safe Navigation Operator

All of these things that you can do rely on the underlying magic that Ruby provides with the **&** operator

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o8pddgra70kfea2xof66.jpg)

## & just works, ok?

The first use we will explore is using **&** to allow us to pass a block to a method and do something useful with it.

```ruby
def pretty_print(&block)
puts '**' << block.call.to_s << '**'
end

pretty_print {'hello world'}
```

That looks just like a regular method, only with braces, right? Not exactly. What would happen if you passed an enumerable? Suppose "('a'..'j').to_a" was our array of characters to be converted to uppercase before showing the entire array.

```ruby
pretty_print { ('a'..'j').to_a.map do |letter| letter.upcase end }
```

You can't do this with a method parameter. The following doesn't work since it can't convert the Array to a String implicitly.

```ruby
def test_print(t)
  puts '**' << t << '**'
end

test(('a'..'j').to_a.map do |letter| letter.upcase end )
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/b3q6qcrzdxfbb7u5u6m7.jpg)

## Shortening enumerables

What was happening in our example above was **&** represented the block that we passed to it. In fact **&** converts what you pass to it into either a block or proc, depending on how it is used. A common use is with #map and other enumerable methods that return a new array.

If you are using #map to create a new array from an existing object, you can likely cut down on some typing. Refactoring the example above would look like this.

```ruby
pretty_print { ('a'..'j').to_a.map(&:upcase) }
```

Since we passed a block to **&**, Ruby converted this to a proc for us and the symbol *:upcase* refers to the method upcase which is available to the enumerable item. This could be useful with models that have a single attribute that you want an array of. For example, we could create an instance variable in one of our models.

```ruby
@all_cats = Owners.all.map(&:cat)
```

Nice and simple.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wgz002uh5fsfjtzadmd9.jpeg)

## Safe Navigation Marker

Another use for **&** is when you want to check a value, but just want *nil* back if it doesn't exist instead of the dreaded NoMethodError. This allows you to presume and not worry if something doesn't exist, you are prepared to get *nil* back.

```ruby
@owner&.cat&.name
```

This is shorter an much easier to read than its counterpart

```ruby
if @owner.cat
  @owner.cat.name
else
  nil
end
```

It is even better than the ternary version.

```ruby
@owner.cat ? @owner.cat.name : nil
```

In this case, **&** is still converting what you pass to it as a block, but since the action occurs inside **&**'s block, if @owner doesn't have a cat and therefore the method for getting the cat's name doesn't exist, the block will evaluate to *nil* instead of throwing an error.

A powerful place to use this last example would be in a view page. You can lazily assume that parameters exist and just expect a *nil* output when that parameter or method doesn't exist.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/58z2pvdeirgbcqi1f555.jpg)

## And then?

There is also the bitwise use of **&** which wasn't covered in this blog. Stay tuned for more. **&** is an enigmatic symbol that produces interesting and useful ways to create flexible methods that wrap around other methods. Thank you for reading my blog and helping me understand these issues better with you.