<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Iago Effting</title>
    <description>The latest articles on DEV Community by Iago Effting (@iagoeffting).</description>
    <link>https://dev.to/iagoeffting</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F20681%2F7cb0dd1a-30a2-481e-9dbe-e917cf4cbc00.jpeg</url>
      <title>DEV Community: Iago Effting</title>
      <link>https://dev.to/iagoeffting</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iagoeffting"/>
    <language>en</language>
    <item>
      <title>Configurando NeoVim + Elixir</title>
      <dc:creator>Iago Effting</dc:creator>
      <pubDate>Tue, 21 May 2024 18:20:25 +0000</pubDate>
      <link>https://dev.to/iagoeffting/configurando-neovim-elixir-2c59</link>
      <guid>https://dev.to/iagoeffting/configurando-neovim-elixir-2c59</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;De idas e vindas acabei trabalhando muito tempo com elixir no VS Code. Até então tudo certo. De um tempo para cá, comecei a sentir lentidão no autocomplete e dificuldade de utilizar algumas ferramentas. Isso me levou a fazer essa pergunta no twitter / X.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1791535928894230872-963" src="https://platform.twitter.com/embed/Tweet.html?id=1791535928894230872"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1791535928894230872-963');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1791535928894230872&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;Trabalhei a alguns anos atrás com VIM e no geral gostava dele, mas achava complexo a configuração e customização. Com isso em mente fui ver como funcionava a configuração do &lt;code&gt;Nvim&lt;/code&gt; que muitos comentaram na thread. Fui atras também de um jeito fácil de configurar e encontrei o &lt;code&gt;Astronvim&lt;/code&gt; que me interessou bastante. Tendo isso em mãos, iniciei o setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuração
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;NeoVim&lt;/li&gt;
&lt;li&gt;AstroNvim&lt;/li&gt;
&lt;li&gt;Elixir-tools&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Instalações
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Requisitos
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requisitos&lt;/th&gt;
&lt;th&gt;Versão&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;neovim&lt;/td&gt;
&lt;td&gt;0.9.5+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  NeoVim
&lt;/h3&gt;

&lt;p&gt;A versão estável atual do Nvim é o 0.7.x, porém, Astronvim pede 0.8+. Isso buscando das versões não estáveis. Tendei diretamente pelo repositório &lt;a href="https://launchpad.net/~neovim-ppa/+archive/ubuntu/stable" rel="noopener noreferrer"&gt;unstable&lt;/a&gt; e instalar a versão &lt;code&gt;nighty&lt;/code&gt;. Porém, me trouxe muitos problemas que não tive paciência para ir em frente. Foi então que me lembrei do gerencias &lt;a href="https://asdf-vm.com/" rel="noopener noreferrer"&gt;asdf&lt;/a&gt; e por ele ficou mais simples&lt;/p&gt;

&lt;p&gt;Repositório: &lt;a href="https://github.com/richin13/asdf-neovim" rel="noopener noreferrer"&gt;https://github.com/richin13/asdf-neovim&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

asdf plugin add neovim
asdf &lt;span class="nb"&gt;install &lt;/span&gt;neovim 0.10.0


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Feito. Nvim instalado. Porém, se você rodar o nvim agora, ele vai receber o erro&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

No version is set for command nvim


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Precisamos definir a versão padrão para a ferramenta. Caso não exista, precisamos criar o arquivo no root do seu usuário. &lt;code&gt;~/.tool-versions&lt;/code&gt; e adicione no conteúdo a ferramenta e a versão&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

neovim 0.10.0


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Com isso, podemos rodar o comando e abrir a ferramenta&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

nvim


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  AstroNvim
&lt;/h2&gt;

&lt;p&gt;Astro é uma ferramenta que une extensibilidade com gerenciamento de plugin utilizando o Mason. Ele facilita a adição de novos plugins e o gerenciamento de dependencia e configurações, por isso decidi usar ele.&lt;/p&gt;

&lt;p&gt;E tive uma boa impressão. ele é simples de rodar, basta seguir o guia oficial e tudo funciona como deveria.&lt;/p&gt;

&lt;p&gt;A configuração é simples&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/AstroNvim/template ~/.config/nvim &lt;span class="c"&gt;# baixa e coloca a configuração no local certo&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/.config/nvim/.git &lt;span class="c"&gt;# Remove o .git do que foi clonado&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ Uma atualização no AstroLSP está quebrando o template acima. Para resolver isso simplesmente substitui pela &lt;a href="https://github.com/AstroNvim/astrolsp?tab=readme-ov-file#%EF%B8%8F-configuration" rel="noopener noreferrer"&gt;configuração da doc&lt;/a&gt;. Caso você tenha feito alguma alteração, vai precisar fazer um de para =D&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Depois disso, bastou rodar o nvim e ele já saiu funcionando&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

nvim


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Você pode receber o erro que não encontrou o compilador C. Para isso precisa ter as dependêmncias base. No linux temos o pacote essencial.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 sudo apt-get install build-essential 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Depois disso só abrir novamente o &lt;code&gt;nvim&lt;/code&gt; e o erro deve ter sumido.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgick2ndmkty5lax3rpci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgick2ndmkty5lax3rpci.png" alt="Nvim rodando"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao abrir, ele começa a instalar as dependências automaticamente. Lindo demais &amp;lt;3&lt;/p&gt;

&lt;p&gt;Talvez você tenha problema com a font e icones. Para isso, instale a nerdfonts no &lt;a href="https://www.nerdfonts.com/font-downloads" rel="noopener noreferrer"&gt;link&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Eu instalei a font 0xProto Nerd Font e ficou bom para mim =D&lt;/p&gt;

&lt;h3&gt;
  
  
  Elixir-tools
&lt;/h3&gt;

&lt;p&gt;Precisei adicionar suporte a linguagem. Para minha surpresa, foi fácil. Existe esse plugin para &lt;code&gt;NeoVim&lt;/code&gt; que da suporte a tudo que precisamos do elixir o &lt;a href="https://github.com/elixir-tools/elixir-tools.nvim" rel="noopener noreferrer"&gt;Elixir-tools&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para isso precisamos acessar a pasta de configuração do &lt;code&gt;nvim&lt;/code&gt;, mesmo lugar que fizemos o clone do astro.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd ~/.config/nvim


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Essa é a estrutura das configurações&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

.nvim/
├─ lua/
│  ├─ plugins/
│  │  ├─ ...
│  ├─ community.lua
│  ├─ lazy_setup.lua
│  ├─ polish.lua
.neoconf.json
.stylua.toml
init.lua
lazy-lock.json
neovim.yml
README.md
selene.toml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;De forma visual, fica fácil saber onde adicionar um plugin, não? Criei um novo arquivo dentro de &lt;code&gt;.nvim/lua/plugins/&lt;/code&gt; e o chamei de &lt;code&gt;elixir.lua&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dentro da documentação do plugin elixir-tools, tem uma seção de &lt;a href="https://github.com/elixir-tools/elixir-tools.nvim?tab=readme-ov-file#lazynvim" rel="noopener noreferrer"&gt;configuração usando o lazy.nvim&lt;/a&gt;, resolvi usar ele. &lt;/p&gt;

&lt;p&gt;Dentro do arquivo &lt;code&gt;.nvim/lua/plugins/elixir.lua&lt;/code&gt; adicionei a configuração para o lazy e um retorno para devolver a configuração&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"elixir-tools/elixir-tools.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"BufReadPre"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"BufNewFile"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;elixir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"elixir"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;elixirls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"elixir.elixirls"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;elixir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;nextls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="n"&gt;credo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="n"&gt;elixirls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elixirls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;dialyzerEnabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;enableTestLenses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;on_attach&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bufnr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;space&amp;gt;fp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;":ElixirFromPipe&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;noremap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
          &lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;space&amp;gt;tp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;":ElixirToPipe&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;noremap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
          &lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;space&amp;gt;em"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;":ElixirExpandMacro&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;noremap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"nvim-lua/plenary.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;feito isso, fechei meu nvim e abri ele diretamente em um arquivo elixir.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

nvim some_place/file.ex


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ele começou a perguntar se queria instalar o &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nextls &lt;/li&gt;
&lt;li&gt;Credo Language Server&lt;/li&gt;
&lt;li&gt;ElixirLS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E eu, so aceitei. Feito isso, tudo funcionou bem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4ga0ngepn8wk9jxsyd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4ga0ngepn8wk9jxsyd1.png" alt="NVim funcionando"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problemas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Versão do NeoVim 0,11+ me dava muitos warnings que resolvi voltando para a 0.10 usando asdf&lt;/li&gt;
&lt;li&gt;Tive problema de permissão também, resolvido mudando a permissão da pasta.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Agradecimentos
&lt;/h2&gt;

&lt;p&gt;A thread teve vários comentários e queria agradecer todos que participaram &amp;lt;3&lt;/p&gt;

</description>
      <category>elixir</category>
    </item>
    <item>
      <title>Dicas e truques Elixir lang</title>
      <dc:creator>Iago Effting</dc:creator>
      <pubDate>Thu, 03 Nov 2022 13:00:56 +0000</pubDate>
      <link>https://dev.to/iagoeffting/dicas-e-truques-de-elixir-ec2</link>
      <guid>https://dev.to/iagoeffting/dicas-e-truques-de-elixir-ec2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Última atualização:&lt;/strong&gt; 01/10/2022&lt;br&gt;
&lt;strong&gt;Elixir:&lt;/strong&gt; 1.14&lt;/p&gt;
&lt;h2&gt;
  
  
  Uma rápida e importante introdução
&lt;/h2&gt;

&lt;p&gt;Esse artigo está vivo! Vou revisita-lo no momento onde achar conveniente, seja quando precisar atualizar ou corrigir algo. Se algo mudar na linguagem onde possamos tirar um maior proveito, eu irei reescrever parte do artigo e não criarei um segundo, utilizarei sempre esse =D&lt;/p&gt;

&lt;p&gt;Bora lá!&lt;/p&gt;
&lt;h2&gt;
  
  
  Dicas&amp;amp;Truques
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Funções anónimas e Pattern match&lt;/li&gt;
&lt;li&gt;Utilizando pipeline e with&lt;/li&gt;
&lt;li&gt;Guard clause&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Pattern match e Funções anónimas
&lt;/h2&gt;

&lt;p&gt;Quando seu código precisa se mover livremente, de acordo com o tipo e/ou valor de dados de entrada, a primeira coisa que brota em nossas cabeças são condicionais, certo? O que faz total sentido. Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# usando condicional case&lt;/span&gt;
&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:member&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;_user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:unknown&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Já utilizamos pattern match ali em cima na condição de cada case, mas podemos extrair um pouco mais dele quando utilizamos funções anónimas.&lt;/p&gt;

&lt;p&gt;Temos um truque que deixa as coisas mais emocionante e conciso. Você não precisa do escopo da função definido, basta resolver tudo diretamente nos parâmetros dela:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# usando pattern match na função anónima&lt;/span&gt;
&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:member&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;
  &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;
  &lt;span class="n"&gt;_user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:unknown&lt;/span&gt;           
 &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;⚠ Lembrando ⚠:&lt;/strong&gt; Isso só funciona com funções anónimas. Funções nomeadas precisam da definição de seu escopo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declaração With e legibilidade
&lt;/h2&gt;

&lt;p&gt;Quando encontramos algo novo que gostamos, usamos em todos os lugares ou mostramos para todas as pessoas.&lt;/p&gt;

&lt;p&gt;Pipes foram assim para mim. Achei eles tão bonitos que queria usar para tudo. Mas ai coisas assim aconteciam:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# usando pipes&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;validate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;update_user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;handle_response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A primeira vista é bonito, passa rapidamente o propósito dos pipes e o que queremos atingir, mas nos trás algumas complicações. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;O dado que passa por todos os pipes devem ser o mesmo ou a próxima função do pipe deve saber qual é a resposta da anterior. Então Pablito sabe demais.&lt;/li&gt;
&lt;li&gt;O tratamento de erro vai para dentro da próxima função ou o pipe quebra. Caso &lt;code&gt;get_user&lt;/code&gt; retorne um &lt;code&gt;{:error, reason}&lt;/code&gt; quem irá tratar vai ser o &lt;code&gt;validate_user&lt;/code&gt; o que é estranho.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Caso sintam algum desses problemas, o elixir consegue nos ajudar. Existe uma função chamada &lt;a href="https://hexdocs.pm/elixir/1.14.1/Kernel.SpecialForms.html#with/1"&gt;with&lt;/a&gt; que irá nos dar uma mão.&lt;/p&gt;

&lt;p&gt;A mesma lógica, mas feita com &lt;code&gt;with&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# usando with com tratamento de erros&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_validate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;validate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_updated&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;update_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_validated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_updated&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- aqui está nossa resposta do with&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:not_found&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"User not found"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:unprocessable_entity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Params are wrong"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:duplicated_user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"User need to be unique"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código se torna maior, mas ganhamos algumas coisas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;as funções subsequentes não precisam entender nada das anteriores e vice-versa.&lt;/li&gt;
&lt;li&gt;O tratamento de erro sai da função. Uma vez que a pattern match não se satisfazer pela definição do &lt;code&gt;with&lt;/code&gt; como no exemplo &lt;code&gt;with {:ok, user} &amp;lt;- get_user(id)&lt;/code&gt; o &lt;code&gt;with&lt;/code&gt; vai parar e cair no escopo &lt;code&gt;else&lt;/code&gt; onde podemos fazer tratamentos utilizando diretamente o pattern match.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Também podemos isolar os erros, onde o tratamento passa a ser feito por outro modulo. O &lt;a href="https://www.phoenixframework.org/"&gt;phoenix&lt;/a&gt; faz isso com os controllers, chamando a estratégia de &lt;a href="https://hexdocs.pm/phoenix/Phoenix.Controller.html#action_fallback/1"&gt;fallback_controller&lt;/a&gt; deixando o código limpo e claro.&lt;/p&gt;

&lt;p&gt;Resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# usando with simplificado&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_validate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;validate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_updated&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;update_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_validated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_updated&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- aqui está nossa resposta do with&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Obs.: Gosto de pipes, de verdade. Mas utilizo eles onde tenho um controle mais restrito, isso é um gosto meu. Não seria um problema para mim, por exemplo, utilizar o pipe dentro de &lt;code&gt;user_validate&lt;/code&gt; onde eu tenho controle de tudo. Mas uma vez que eu pegue funções de módulos diferente, acabo tentando tentando desacoplar lógica de dentro das funções que não a pertencem. É uma escolha minha e que me ajudou até então. Existem outras formas, essa é apenas uma delas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Guard clause
&lt;/h2&gt;

&lt;p&gt;Eu particularmente gosto dessa. Vamos supor que precisamos que um dado dentro de um &lt;code&gt;map&lt;/code&gt; e esse dado esteja bem dentro, uns 3 níveis. Com esse dado eu tenho que saber o que irei fazer em seguida. O fluxo se alteraria dependendo dele. Como podemos resolver isso? A forma mais clássica é utilizando &lt;code&gt;cond&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos a um exemplo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# usando condicional cond&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;cond&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;is_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;far&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Integer: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;far&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;is_bitstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;far&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"String: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;far&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I don't know what hack is that: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;far&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Relativamente elegante, porém meio grande certo? Utiliza boas funções para fazer o desvio de fluxo. Porém, alguns problemas aparecem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Essa função vai crescer com a quantidade de N tratamentos que precisarmos (se fosse por aqui o SOLID iria ferir o &lt;a href="https://imasters.com.br/codigo/solid-de-verdade-open-closed-principle-ocp"&gt;open/close principle&lt;/a&gt;, mas falaremos disso talvez uma outra hora). &lt;/li&gt;
&lt;li&gt;Fazer dessa forma pode dificultar a criação de tests devido a dificuldade de gerar o cenário (ainda esta simples ali, mas pense nas infinitas possibilidades)&lt;/li&gt;
&lt;li&gt;Também teremos que nos certificar de que quando essa função mudar, todos os cenários podem mudar junto, mesmo não tendo uma relação.&lt;/li&gt;
&lt;li&gt;em alguma hora a leitura será prejudicada também. Facilmente vejo essa função crescer pra mais de 200 linhas and beyond.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Podemos resolver isso usando algo chamado &lt;code&gt;guard clause&lt;/code&gt; diretamente na definição da função. E a leitura fica linda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# utilizando guard clause e pattern match&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;data:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;inside:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Integer: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;data:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;inside:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_bitstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"String: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I don't know what the hack is that: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;o interessante disso é:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A leitura fica simples&lt;/li&gt;
&lt;li&gt;Podemos facilmente trocar de módulos cada um deles, caso a implementação cresça&lt;/li&gt;
&lt;li&gt;Mantemos um contrato claro do que precisamos para a função funcionar.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;⚠ Lembrando ⚠:&lt;/strong&gt; Guard clause so funcionam com tipos primitivos e não funcionam com funções de módules, como por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# exemplos de utilização de guard clause&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# ... ✅&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# ... ✅&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# ... ✅&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="no"&gt;MyModule&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# ... ❌&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://hexdocs.pm/elixir/guards.html#list-of-allowed-expressions"&gt;Aqui esta uma lista do que ele permite&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Todas essas dicas devem ser pensadas e levado em consideração o cenário que será utilizado. O importante é facilitar a vida do programador ao realizar alguma manutenção (não so você, como todo o seu time e futuro membros). Se a escolha for consciente, você estará bem para ir, caso não, você vai se transformar em um desenvolvedor que deseja fazer tudo inline ou com menos código, e isso é muito sério, você mata a facilidade de entendimento e leitura de código por causa de ego. Não seja assim.&lt;/p&gt;

&lt;p&gt;Caso você esteja consciente disso, divirta-se refatornando trechos de códigos difíceis de ler e veja se alguma dessas dicas lhe foi útil, caso tenha sido, conte para nós nos comentários.&lt;/p&gt;




&lt;p&gt;Já que você chegou até aqui, se inscreva no &lt;a href="https://semanal.cafecomelixir.com.br"&gt;Café com Elixir&lt;/a&gt; uma newsletter semanal de Elixir focado em conteúdos da comunidade brasileira.&lt;/p&gt;

&lt;p&gt;Me sigam também no twitter &lt;a href="https://twitter.com/iagoEffting"&gt;@iagoEffting&lt;/a&gt; lá sou mais ativo =D&lt;/p&gt;

&lt;p&gt;E se inscrevam no canal no &lt;a href="https://www.youtube.com/c/IagoEffting"&gt;youtube&lt;/a&gt; &lt;/p&gt;

</description>
      <category>elixir</category>
      <category>dicas</category>
      <category>iniciante</category>
    </item>
    <item>
      <title>Como utilizar generators no Phoenix</title>
      <dc:creator>Iago Effting</dc:creator>
      <pubDate>Thu, 27 Oct 2022 19:22:00 +0000</pubDate>
      <link>https://dev.to/iagoeffting/como-utilizar-generators-no-phoenix-5die</link>
      <guid>https://dev.to/iagoeffting/como-utilizar-generators-no-phoenix-5die</guid>
      <description>&lt;p&gt;Quando acordamos de manhã cedo e pensamos em fazer nossa mais nova ideia milionária, sempre vem na cabeça (pelo menos na minha) em colocar esse produto em uma aplicação web, para facilitar o acesso.&lt;/p&gt;

&lt;p&gt;No mundo Elixir uma das melhores ferramentas para construir isso é o &lt;a href="https://www.phoenixframework.org/"&gt;Phoenix Framework&lt;/a&gt;. Ele possui todas as funcionalidades que precisamos e muito mais.&lt;/p&gt;

&lt;p&gt;Convenhamos que ideias vem o tempo todo e queremos faze-las e valida-las o mais rápido possível antes que percamos o foco (ou a vontade). Mas, como podemos acelerar o processo de criação?&lt;/p&gt;

&lt;p&gt;Phoenix possui uma gama de generators que podem te ajudam a gerar código de problemas comuns, que basicamente se repetem ao longo da história e é sobre os generators que eu falarei aqui.&lt;/p&gt;

&lt;h4&gt;
  
  
  O que veremos?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Gerando uma nova aplicação web com &lt;code&gt;mix phx.new ...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Gerando contexto, controller, views e html com &lt;code&gt;mix phx.gen.html&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Gerando autenticação com &lt;code&gt;mix phx.gen.auth&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Protegendo rotas com autenticação&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Para iniciar, essa é a ideia milionária:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Desafio de hoje:&lt;/strong&gt; Na nossa mais nova ideia, precisamos criar um painel administrativo onde possamos cadastrar filmes. Os campos necessários são &lt;code&gt;title&lt;/code&gt; e &lt;code&gt;description&lt;/code&gt;. Nossos usuários precisarão estar logado para interagir com o sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requisitos tecnológicos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elixir-lang.org/install.html"&gt;Instalar Elixir&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/phoenix/installation.html"&gt;Instalar Phoenix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Criando nossa aplicação
&lt;/h2&gt;

&lt;p&gt;Nossa aplicação terá a necessidade de um banco de dados (utilizaremos o postgres), também o suporte a HTML. &lt;/p&gt;

&lt;p&gt;O primeiro gerador que utilizaremos dará conta dissoPodemos passar comandos simples para o cli do phoenix configurar isso para nós:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix phx.new my_movies &lt;span class="nt"&gt;--database&lt;/span&gt; postgres &lt;span class="nt"&gt;--no-live&lt;/span&gt;

...
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/lib/my_movies/mailer.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/lib/my_movies_web/gettext.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/priv/gettext/en/LC_MESSAGES/errors.po
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/priv/gettext/errors.pot
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/assets/css/phoenix.css
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/assets/css/app.css
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/assets/js/app.js
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/priv/static/robots.txt
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/priv/static/images/phoenix.png
&lt;span class="k"&gt;*&lt;/span&gt; creating my_movies/priv/static/favicon.ico

Fetch and &lt;span class="nb"&gt;install &lt;/span&gt;dependencies? &lt;span class="o"&gt;[&lt;/span&gt;Yn]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;--no-live&lt;/code&gt; diz para nosso gerador que não utilizaremos live view. O &lt;code&gt;--database&lt;/code&gt; seta para nós o banco que utilizaremos (potgres é o default, então não precisaria dele ali, mas para deixar mais claro, adicionei. Também da suporte a &lt;code&gt;mysql&lt;/code&gt; a &lt;code&gt;mssql&lt;/code&gt;, &lt;code&gt;sqlite3&lt;/code&gt; e outros.&lt;/p&gt;

&lt;p&gt;No fim da operação o terminal ira perguntar se quer instalar as dependências. Pode ser feito depois, mas eu ja apertei &lt;code&gt;Y&lt;/code&gt; aqui enquanto tomava um gole de café.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Fetch and &lt;span class="nb"&gt;install &lt;/span&gt;dependencies? &lt;span class="o"&gt;[&lt;/span&gt;Yn] Y
&lt;span class="k"&gt;*&lt;/span&gt; running mix deps.get
&lt;span class="k"&gt;*&lt;/span&gt; running mix deps.compile

We are almost there! The following steps are missing:

    &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my_movies

Then configure your database &lt;span class="k"&gt;in &lt;/span&gt;config/dev.exs and run:

    &lt;span class="nv"&gt;$ &lt;/span&gt;mix ecto.create

Start your Phoenix app with:

    &lt;span class="nv"&gt;$ &lt;/span&gt;mix phx.server

You can also run your app inside IEx &lt;span class="o"&gt;(&lt;/span&gt;Interactive Elixir&lt;span class="o"&gt;)&lt;/span&gt; as:

    &lt;span class="nv"&gt;$ &lt;/span&gt;iex &lt;span class="nt"&gt;-S&lt;/span&gt; mix phx.server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finalizando o processo devemos entrar na pasta do projeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my_movies 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora falta so configurar o banco de dados em &lt;code&gt;config/dev.exs&lt;/code&gt;. Eu uso para fins de estudo o default, então meu está igual ao gerado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:my_movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyMovies&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;hostname:&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;database:&lt;/span&gt; &lt;span class="s2"&gt;"my_movies_dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;stacktrace:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;show_sensitive_data_on_connection_error:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;pool_size:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De volta ao terminal, precisamos rodar o setup da aplicação para conseguir executar ela. Utilizarei o comando &lt;code&gt;mix setup&lt;/code&gt; onde ele ja vai fazer para mim o &lt;code&gt;mix deps.get&lt;/code&gt; e &lt;code&gt;mix ecto.setup&lt;/code&gt; (que vai criar o banco para nós e rodar a migration caso tenha)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix setup

Compiling 14 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated my_movies app
The database &lt;span class="k"&gt;for &lt;/span&gt;MyMovies.Repo has already been created

14:25:38.948 &lt;span class="o"&gt;[&lt;/span&gt;info] Migrations already up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não se preocupe com o warning do &lt;code&gt;gettext&lt;/code&gt; ele não morde. Porém se voce se incomodar com o &lt;code&gt;warning&lt;/code&gt; pode ir no mix.exs e remover ele do compilers.&lt;/p&gt;

&lt;p&gt;Pronto, tudo configurado e bom para ir. Para garantir vitória so executar o comando de inicializar o nosso server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix phx.server

&lt;span class="o"&gt;[&lt;/span&gt;info] Running MyMoviesWeb.Endpoint with cowboy 2.9.0 at 127.0.0.1:4000 &lt;span class="o"&gt;(&lt;/span&gt;http&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;debug] Downloading esbuild from https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.29.tgz
&lt;span class="o"&gt;[&lt;/span&gt;info] Access MyMoviesWeb.Endpoint at http://localhost:4000
&lt;span class="o"&gt;[&lt;/span&gt;watch] build finished, watching &lt;span class="k"&gt;for &lt;/span&gt;changes..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos então abrir nossa aplicação no browser &lt;a href="http://localhost:4000"&gt;http://localhost:4000&lt;/a&gt;. Vai, clica ai, confia.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OZWymwyj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8b4jd9owupo71rvbv2qs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OZWymwyj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8b4jd9owupo71rvbv2qs.png" alt="Pagina inicial da aplicacao" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Proximo passo: Criar nossa página para cadastrar, ler, editar e deletar um filme. (famoso CRUD)
&lt;/h2&gt;

&lt;p&gt;e ai que entra nosso primeiro generate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bufdc3hu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2Az6Wq622lYQ1y2_qIaDNwJA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bufdc3hu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2Az6Wq622lYQ1y2_qIaDNwJA.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Segura ai, ainda não iremos tocar no código.&lt;/p&gt;

&lt;p&gt;Na documentação do Phoenix temos &lt;a href="https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.html"&gt;outros generators&lt;/a&gt; que podem nos ser útil. Em nosso CRUD precisamos do pacote completo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;schema:&lt;/strong&gt; A estrutura de nosso Filme&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;migration:&lt;/strong&gt; O comando para criar a sua tabela no banco de dados&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;context:&lt;/strong&gt; um lugar para ele viver&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;controller:&lt;/strong&gt; um lugar para acessar ele&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;view:&lt;/strong&gt; uma forma de alterar sua exibição&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dois generator atendem a esse requisito:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;phx.gen.json&lt;/li&gt;
&lt;li&gt;phx.gen.html&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora vai de você escolher como voce vai expor seu programa. Nós aqui iremos utilizar HTML, logo &lt;a href="https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Html.html"&gt;phx.gen.html&lt;/a&gt; será utilizado.&lt;/p&gt;

&lt;p&gt;Nossa regra para isso será:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Temos um catalogo&lt;/li&gt;
&lt;li&gt;No catalogo podemos adicionar, ver, listar e deletar filmes&lt;/li&gt;
&lt;li&gt;os filmes terão titulo e descrição apenas&lt;/li&gt;
&lt;li&gt;os filmes serão salvos na tabela &lt;code&gt;movies&lt;/code&gt; no banco de dados&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bora para o terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix phx.gen.html Catalog Movie movies title:string description:string

&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/controllers/movie_controller.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/templates/movie/edit.html.heex
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/templates/movie/form.html.heex
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/templates/movie/index.html.heex
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/templates/movie/new.html.heex
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/templates/movie/show.html.heex
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/views/movie_view.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/my_movies_web/controllers/movie_controller_test.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies/catalog/movie.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating priv/repo/migrations/20221027161657_create_movies.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies/catalog.ex
&lt;span class="k"&gt;*&lt;/span&gt; injecting lib/my_movies/catalog.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/my_movies/catalog_test.exs
&lt;span class="k"&gt;*&lt;/span&gt; injecting &lt;span class="nb"&gt;test&lt;/span&gt;/my_movies/catalog_test.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/support/fixtures/catalog_fixtures.ex
&lt;span class="k"&gt;*&lt;/span&gt; injecting &lt;span class="nb"&gt;test&lt;/span&gt;/support/fixtures/catalog_fixtures.ex

Add the resource to your browser scope &lt;span class="k"&gt;in &lt;/span&gt;lib/my_movies_web/router.ex:

    resources &lt;span class="s2"&gt;"/movies"&lt;/span&gt;, MovieController


Remember to update your repository by running migrations:

    &lt;span class="nv"&gt;$ &lt;/span&gt;mix ecto.migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No final do comando ele pede para fazer algumas ações.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adicionar o &lt;code&gt;resources "/movies", MovieController&lt;/code&gt; em nossas rotas &lt;code&gt;lib/my_movies_web/router.ex&lt;/code&gt;. Iremos colocar em acesso publico (sem restrição por não estar logado)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyMoviesWeb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:browser&lt;/span&gt;

  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PageController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="s2"&gt;"/movies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MovieController&lt;/span&gt; &lt;span class="c1"&gt;# adicione essa linha&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;rodar a migração que o gerador criou para nós.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix ecto.migrate

13:26:53.578 &lt;span class="o"&gt;[&lt;/span&gt;info] &lt;span class="o"&gt;==&lt;/span&gt; Running 20221027161657 MyMovies.Repo.Migrations.CreateMovies.change/0 forward

13:26:53.581 &lt;span class="o"&gt;[&lt;/span&gt;info] create table movies

13:26:53.597 &lt;span class="o"&gt;[&lt;/span&gt;info] &lt;span class="o"&gt;==&lt;/span&gt; Migrated 20221027161657 &lt;span class="k"&gt;in &lt;/span&gt;0.0s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O gerador fez bastante coisa né? Sugiro dar uma olhada no que foi adicionado e criado. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Uma nota:&lt;/strong&gt; nem sempre vem como queremos, tendo muitas vezes que fazer mudanças. Os generators são uma base para adiantarmos nosso trabalho, ele não vai te entregar exatamente o que você precisa.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A não ser que você queira um CRUD simples e esse é o nosso caso! Rode a aplicação para ver o que aconteceu.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix phx.server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E vamos entrar na nova rota criada: &lt;a href="http://localhost:4000/movies"&gt;http://localhost:4000/books&lt;/a&gt;, aperta ai ;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--56zsFObo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi7qi2lig2l4yt538yxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--56zsFObo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi7qi2lig2l4yt538yxx.png" alt="tela" width="880" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A segunda etapa do nosso sistema esta pronto. Podemos criar, listar. editar e deletar filmes. 🎉 &lt;/p&gt;

&lt;p&gt;Mas está meio estranho esse admin ter acesso por todos sem um login e senha não? 🤔&lt;/p&gt;

&lt;p&gt;Sim e vamos resolver agora!&lt;/p&gt;

&lt;h2&gt;
  
  
  Gerando autenticação
&lt;/h2&gt;

&lt;p&gt;Podemos também gerar essa parte do sistema, adiantando e muito nosso sistema. Utilizaremos o &lt;a href="https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Auth.html"&gt;phx.gen.auth&lt;/a&gt; para isso.&lt;/p&gt;

&lt;p&gt;A regra para isso sera:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Precisamos que nosso usuário tenha uma conta com email e senha&lt;/li&gt;
&lt;li&gt;Precisamos validar via link se o e-mail existe de fato.&lt;/li&gt;
&lt;li&gt;Precisamos realizar o loggin do usuario&lt;/li&gt;
&lt;li&gt;Precisamos dar a possibilidade do logout&lt;/li&gt;
&lt;li&gt;Precisamos proteger nossa rota de filmes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's go&lt;/p&gt;

&lt;p&gt;O phx.gen.auth funciona muito parecido com o phx.gen.html que usamos. Primeiro passamos o contexto, depois o schema e por fim a tabela.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix phx.gen.auth Account user &lt;span class="nb"&gt;users&lt;/span&gt;

...
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies_web/controllers/user_settings_controller.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/my_movies_web/controllers/user_settings_controller_test.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/my_movies/accounts.ex
&lt;span class="k"&gt;*&lt;/span&gt; injecting lib/my_movies/accounts.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/my_movies/accounts_test.exs
&lt;span class="k"&gt;*&lt;/span&gt; injecting &lt;span class="nb"&gt;test&lt;/span&gt;/my_movies/accounts_test.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/support/fixtures/accounts_fixtures.ex
&lt;span class="k"&gt;*&lt;/span&gt; injecting &lt;span class="nb"&gt;test&lt;/span&gt;/support/fixtures/accounts_fixtures.ex
&lt;span class="k"&gt;*&lt;/span&gt; injecting &lt;span class="nb"&gt;test&lt;/span&gt;/support/conn_case.ex
&lt;span class="k"&gt;*&lt;/span&gt; injecting config/test.exs
&lt;span class="k"&gt;*&lt;/span&gt; injecting mix.exs
&lt;span class="k"&gt;*&lt;/span&gt; injecting lib/my_movies_web/router.ex
&lt;span class="k"&gt;*&lt;/span&gt; injecting lib/my_movies_web/router.ex - imports
&lt;span class="k"&gt;*&lt;/span&gt; injecting lib/my_movies_web/router.ex - plug
&lt;span class="k"&gt;*&lt;/span&gt; injecting lib/my_movies_web/templates/layout/root.html.heex

Please re-fetch your dependencies with the following &lt;span class="nb"&gt;command&lt;/span&gt;:

    &lt;span class="nv"&gt;$ &lt;/span&gt;mix deps.get

Remember to update your repository by running migrations:

    &lt;span class="nv"&gt;$ &lt;/span&gt;mix ecto.migrate

Once you are ready, visit &lt;span class="s2"&gt;"/users/register"&lt;/span&gt;
to create your account and &lt;span class="k"&gt;then &lt;/span&gt;access &lt;span class="s2"&gt;"/dev/mailbox"&lt;/span&gt; to
see the account confirmation email.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Duas ações são necessárias&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;gerir dependencias &lt;code&gt;mix deps.get&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;rodar migrations &lt;code&gt;mix ecto.migrate&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;e voce esta bem para ir.&lt;/p&gt;

&lt;p&gt;Mas vamos analisar a parte final que é interessante:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...
Once you are ready, visit &lt;span class="s2"&gt;"/users/register"&lt;/span&gt;
to create your account and &lt;span class="k"&gt;then &lt;/span&gt;access &lt;span class="s2"&gt;"/dev/mailbox"&lt;/span&gt; to
see the account confirmation email.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O generate ja trás para nossas as funções de &lt;code&gt;register&lt;/code&gt;, &lt;code&gt;login&lt;/code&gt; e também &lt;code&gt;confirmation&lt;/code&gt; para saber que o e-mail está correto e assim ativar sua conta.&lt;/p&gt;

&lt;p&gt;Existe diversas configurações que podem ser feitas aqui, recomendo a leitura da documentação e procurar na internet outras formas de customizar isso, é bem interessante e prático.&lt;/p&gt;

&lt;p&gt;continuando...&lt;/p&gt;

&lt;p&gt;Rode novamente o servidor phoenix &lt;code&gt;mix phx.server&lt;/code&gt; e voce verá algumas mudanças no cabeçalho.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o_6s-Xin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5fz0sh9pe8g0d33tyos6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o_6s-Xin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5fz0sh9pe8g0d33tyos6.png" alt="pagina inicial com login e registro" width="880" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora você pode ver no lado direito o &lt;code&gt;register&lt;/code&gt; e o &lt;code&gt;Log in&lt;/code&gt; e server para exatamente isso =D&lt;/p&gt;

&lt;p&gt;Faça o register para ver o que acontece. Uma vez cadastrado as opções la em cima mudam:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dcMMMB3V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g6j3l3acq8abazwheck5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dcMMMB3V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g6j3l3acq8abazwheck5.png" alt="home logado" width="880" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você já possui um sistema de autenticação para usar. Os arquivos gerados estão na sua codebase e você pode alterar a vontade, para suprir suas necessidades.&lt;/p&gt;

&lt;p&gt;Um detalhe interessante, quando se faz o cadastro é enviado um e-mail, mas já que estamos local ele não vai para o mundo externo. Em vez disso ele é pego no meio do caminho e você pode ver ele aqui &lt;a href="http://localhost:4000/dev/mailbox"&gt;http://localhost:4000/dev/mailbox&lt;/a&gt; e fazer a confirmação sem precisar mandar para um provedor de e-mail. Muito util e rápido para testar, não?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P0K3wThf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy9ieuj8f3wccz5mu43l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P0K3wThf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy9ieuj8f3wccz5mu43l.png" alt="dev mailbox" width="880" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Booa, bastante coisa pronta não? Mas faltou uma ultima etapa. Se voce acessar o &lt;code&gt;/movies&lt;/code&gt; sem estar logado ainda poderá realizar as operações, vamos resolver isso. &lt;/p&gt;

&lt;h2&gt;
  
  
  Protegendo rotas privadas
&lt;/h2&gt;

&lt;p&gt;Ao ter gerado a autenticação o seu arquivo &lt;code&gt;router.ex&lt;/code&gt; mudou e agora você tem la alguns plugs e escopos novos.&lt;/p&gt;

&lt;p&gt;Para os recursos de filmes estarem configurados de forma a não deixar pessoas não autenticadas acessar, você precisa usar o plug &lt;code&gt;:require_authenticated_user&lt;/code&gt; no pipe do escopo.&lt;/p&gt;

&lt;p&gt;Depois de gerar a autenticação, foi configurado novas rotas automaticamente (que ja acessamos, como register e Log in). Basta agora mover o &lt;code&gt;resources "/movies", MovieController&lt;/code&gt; para o escopo que já está utilizando o plug ou criar um novo escopo para você. Irei optar por isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/my_movies_web/router.ex&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;

&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyMoviesWeb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:browser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:require_authenticated_user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="s2"&gt;"/movies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MovieController&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código acima, colocamos o recurso de filmes abaixo do escopo &lt;code&gt;admin&lt;/code&gt;, então o acesso na URL mudou sendo agora  &lt;a href="http://localhost:4000/admin/movies"&gt;http://localhost:4000/admin/movies&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Caso esteja logado você conseguirá ver a página normalmente, mas caso não esteja, você será redirecionado para a página de login e uma mensagem será exibida:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bo4xfUCV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o873yid93oncbsbqvaet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bo4xfUCV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o873yid93oncbsbqvaet.png" alt="redirect login" width="880" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basta fazer o login e você será enviado novamente para a listagem de filmes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E2zVe3a7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyo48i1wiyhqg7rtewub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E2zVe3a7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyo48i1wiyhqg7rtewub.png" alt="Listagem de filmes" width="880" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora sim! Tudo pronto 🎉🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Geradores podem causar grandes discussões no mundo do desenvolvimento e por uma boa razão. &lt;/p&gt;

&lt;p&gt;Quando os utilizamos só por utilizar, sem uma consciência do que esta acontecendo, tende a deixar as coisas mais confusas e criar funcionalidades que nunca serão utilizadas. Isso é ruim a longo prazo, onde se torna difícil manter.&lt;/p&gt;

&lt;p&gt;Mas se você está fazendo as escolhas consciente, analisando os impactos que isso possa causar e alterando o código gerado para se adequar ao seu produto, não a mau em utiliza-lo, eles te pouparão um grande tempo.&lt;/p&gt;

&lt;p&gt;Espero que tenham gostado ;)&lt;/p&gt;




&lt;p&gt;Já que você chegou até aqui, se inscreva no &lt;a href="https://www.getrevue.co/profile/iagoeffting"&gt;Café com Elixir&lt;/a&gt; uma newsletter semanal de Elixir focado em conteúdos da comunidade brasileira.&lt;/p&gt;

&lt;p&gt;Me sigam também no twitter &lt;a href="https://twitter.com/iagoEffting"&gt;@iagoEffting&lt;/a&gt; lá sou mais ativo =D&lt;/p&gt;

&lt;p&gt;E se inscrevam no canal no &lt;a href="https://www.youtube.com/c/IagoEffting"&gt;youtube&lt;/a&gt; &lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>generators</category>
      <category>iniciante</category>
    </item>
  </channel>
</rss>
