Para que serve o & antes de um parâmetro em Ruby?

O & antes de algum parâmetro é utilizado basicamente de duas formas:

1 Na definição de um método:

def awesome_method &block
  yield if block_given?
end

2 Antes da chamada de um método:

  awesome_method &parameter

A primeira forma serve para deixar explícito que o seu método recebe um bloco. Já a segunda forma funciona assim: pega o parâmetro, chama o método to_proc e o passa como bloco, idependente de o método ter deixado o bloco explícito ou não. Então basta que o objeto passado responda a to_proc. Você ja deve ter visto parecido com isso:

  @users.map &:name

E uma coisa que sempre quis saber é “como um símbolo passado como parâmetro irá no exemplo acima irá retornar o nome de todos usuários?”. Pesquisei um pouco, e achei como isso é feito Símbolos implementam o to_proc, tá e dai, como funciona esse to_proc`?

  class Symbol
    # ...
    def to_proc
      Proc.new do |obj, *args|
        obj.send self, *args
      end
    end
    # ...

Ainda um pouco confuso? Vamos destrinchar esse código então. vamos chamar o to_proc para o símbolo :name

  #...
  Proc.new do |obj, *args|
    obj.send :name, *args
  end
  #...

o map passa como parâmetro para o bloco um item da coleção, nesse caso um user, vamos adicioná-lo no código, e já que apenas um argumento é passado podemos remover o *args para simplificar.

  #...
  Proc.new do |user|
    user.send :name # => equivalente a user.name
  end
  #...

Mais simples agora? O método send envia para o user a mensagem :name, porque na verdade em Ruby metódos não são chamados, são mensagens enviadas ao objeto. o resultado final seria algo equivalente a isso:

  @users.map do |user|
    user.send :name # ou user.name
  end

Caso queira saber mais sobre o ampersand: Ruby ampersand parameter demystified