04 Aug 2019 - Raul Fernando
Neste post irei falar sobre begin
e rescue
palavras chaves utilizadas no ruby para lidar com erros. Por exemplo, ao tentar acessar um arquivo inexistente ou tentar fazer uma divisão por zero será levantado um erro (uma exception) quando isso acontece o ruby não falhará imediatamente dando ao desenvolvedor a chance lidar com eles caso ocorram, isso geralmente é chamado de “exception handling”.
O ruby nos fornece duas palavras-chaves para lidarmos com as exceptions geradas.
Essas palavras-chave são begin
e rescue
vejamos como utiliza-las
Dentro do begin
tem o código que você vai executar e que pode levantar uma exception. Exemplo:
begin
IO.sysopen('/foo/bar')
rescue
# ...
end
No código acima estamos tentando abrir um arquivo, uma exception será levantada caso o arquivo não possa ser aberto, sendo assim usamos a palavra-chave rescue
para resgatar o erro e adicionarmos o código que lidará com a exception veja o exemplo abaixo:
begin
IO.sysopen('/foo/bar')
rescue
puts "Arquivo não encontrado."
end
Além disso o rescue
pode levar um argumento opcional. Este argumento é a classe da exception que você deseja resgatar, por exemplo o IO
pode levantar um erro de arquivo não encontrado que será Errno::ENOENT
Ou Errno::EACCES
por um erro de permissão. Dito isso existe uma forma para o desenvolvedor manipular varias exceptions no mesmo bloco de (begin
/ rescue
) como mostrado no exemplo abaixo:
begin
IO.sysopen('/foo/bar')
rescue Errno::ENOENT
puts "Arquivo não encontrado."
rescue Errno::EACCES
puts "Você não possui permissão para abrir este arquivo."
end
E se você quiser que o mesmo código seja executado para varias exceptions você poderá faze-lo da seguinte maneira:
begin
IO.sysopen('/foo/bar')
rescue Errno::ENOENT, Errno::EACCES
puts "Houve um erro ao abrir o arquivo.."
end
Uma coisa legal é que nem sempre você precisa usar a palavra-chave begin
, quando dentro de um método ou bloco a mesma pode ser omitida. Veja o exemplo abaixo:
def get_null_device
IO.sysopen('/foo/bar')
rescue Errno::ENOENT
puts "O arquivo solicitado não pode ser aberto."
end
["a.txt", "b.txt", "c.txt"].map do |f|
IO.sysopen(f)
rescue Errno::ENOENT
puts "Can't open IO device: #{f}."
end
A própria definição do método em si faz o trabalho de begin
, então você pode omiti-lo.
Lembrando que é uma boa pratica você lidar com exceptions especificas para evitar esconder erros de você mesmo.