case

O case/2 nos ajuda a condicionar um valor de acordo com diferentes valores de entrada. Ele cairá no caso especificado pelo valor esperado. Normalmente utilizando pattern matching. Um exemplo real:

case HTTPoison.get("http://.../user/1") do
  {:ok, %HTTPoison.Response{body: body, status: 200}} -> Jason.decode(body)
  {:ok, %HTTPoison.Response{body: body, status: 404}} -> {:error, :not_found}
  {:ok, %HTTPoison.Response{body: body, status: 401}} -> {:error, :unauthorized}
  {:error, reason} -> {:error, reason}
end
circle-exclamation

Temos no exemplo uma chamada a um endpoint para resgatar um usuário com o id 1. No mundo real temos vários casos de resposta utilizando pattern matching para cada caso.

  • status: 200 -> Deu tudo certo e o usuário foi retornado no boddy

  • status: 404 -> O usuário com id 1 não foi encontrado

  • status: 401 -> Você não possui autorização para acessar esse endpoint

  • :error -> Algo deu errado na chamada do endpoint mas não possuimos tratamento para isso, logo, vou apenas retornar a razão do erro junto com a tupla de error.

Case se torna um bom recurso para conseguirmos lidar com todos os casos dessa requisição e facilmente trata-las a fim de avisar o usuário ou tentar uma ação corretiva. No nosso caso, apenas alertamos que algo não saiu como o esperado.

Criando nosso código

Vamos a um código mais simples para aplicarmos o conceito.

Utilizaremos o código de autorização feita no estudo de cond/1 . Precisamos obter os dados de um recurso, que vamos chamar aqui de articles. Pra isso o usuário deve estar autorizado a receber a informação. Qualquer nível de funcionário conseguirá realizar essa operação.

Teste falhou por que não temos ainda o módulo Articles. Vamos cria-lo e já adicionar a logica utilizando o Authorizatin.access/1. Vamos fazer esse teste passar o mais simples possível.

Primeira etapa finalizada. Vamos para o segundo problema. Caso você não tenha um nível de acesso acima de 1, você não pode acessar os dados.

Rodando o teste, teremos um relatório de erro.

Temos agora um cenário novo. Quando o seu nível de acesso é baixo, ele não deveria deixar passar. Mas como esta agora voce consegue acessar os artigos normalmente.

Vamos adicionar a checagem de autorização. A autorização responde de duas formas:

  • {:ok, data} => quando algo tem sucesso

  • {:error, reason} => quando algo está errado.

Já que possuimos esses dois cenários e ambos podem ser pegos por pattern matching podemos utilizar case/2 para resolver o problema.

  1. Utilizaremos case/2 com o primeiro argumento a chamada a função Authorization.access/1

  2. Utilizaremos o bloco do para realizar os matchs dos cenários

  3. Retornaremos o valor dependendo do caso.

Dentro do segundo argumento do case/2 temos a chamada do escopo do onde isola o contexto de case. Cada linha dentro do escopo do é um possível cenário a ser coberto. Sendo o lado esquerdo a resposta de Authorization.access (o que foi chamado no primeiro argumento do case/2). Para acessar um caso especifico o pattern matching deve ser válido. Caso não seja ele passa para o proximo match. Caso não encontra nenhum que seja valido ele dispara uma exceção.

Vamos rodar o teste novamente

Tudo funcionando novamente. Com isso você pode criar diversos casos dentro desse case em articles. Como por exemplo:

  • Somente usuários com permissões de level 2 conseguem pegar determinados artigos

  • Quando tivermos level 0 pode ser apenas dito que nada foi encontrado.

Assim você consegue expandir os casos de uma funcionalidade.

Conclusão

Case é uma poderosa ferramenta para ter em sua caixa de ferramentas. Várias bibliotecas a utilizam. Também conseguimos tirar maior proveitos da conveção de tuplas, sendo assim, mais fácil a sua utilização.

Last updated