Método eval em Ruby

Dicas - 22/Nov/2020 - por André Kanamura

O método eval é bastante poderoso, mas deve ser usado com cautela por trazer possíveis brechas de segurança. Ele avalia strings com expressões Ruby e as executa, como no exemplo abaixo:

puts eval "1 + 2 * 3"
7
# => nil

Note como a expressão descrita na string é lida e executada como código. O eval pode também avaliar e executar strings com código complexo:

eval("def hello; puts 'Hello!'; end")
# => :hello

hello
Hello!

No exemplo acima, o método eval recebe uma string cujo código, quando executado, define o método hello. Essa funcionalidade é extremamente poderosa, já que podemos manipular strings e executar código Ruby por meio delas. No entanto, isso pode ser perigoso caso essas strings sejam, por exemplo, enviadas ou manipuladas por usuários de uma aplicação, pode acontecer algo parecido com um ataque de injeção SQL.

Uma coisa interessante desse método é que ele interpreta variáveis de seu escopo, então, é possível fazer coisas como:

a_text = "Este é um texto"

eval("a_text.split(' ')")
 => ["Este", "é", "um", "texto"]

Como este método pode abrir brechas de segurança, seu uso não é recomendado. Além disso, existem outras maneiras de obter os mesmos resultados que não dependem do eval. Em Ruby existe o public_send, que permite chamar outros métodos cujo nome você possui na forma de string ou symbol, e o define_method, que, como o nome diz, permite definir métodos de instância.

Vamos considerar, por exemplo, que temos uma string "2 + 3" e queremos realizar esse cálculo. Poderíamos fazer algo como:

operation = "2 + 3".split(' ')
operation[0].to_i.public_send(operation[1], operation[2])
# => 5

Considere agora que precisamos criar um método com um nome definido em uma string. Podemos utilizar o define_method:

nome = "nome_do_metodo"
define_method(nome) { |n| puts "#{ n }"  }
# => :nome_do_metodo 

nome_to_metodo("Criei um método")
Criei um método
# => nil

Conclusão

Metaprogramação é parte integrada na linguagem de programação Ruby e, apesar de existirem alternativas melhores, o método eval é uma das ferramentas que permite um código manipular outros códigos. Em Ruby, encontramos também o class_eval e o instance_eval, que oferecem formas diferentes de avaliar strings ou blocos de código. Você pode ver mais sobre essas alternativas nos links abaixo.

Referências

Foto de perfil do autor
André Kanamura

Dev na Campus Code