<?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: Rômulo Silva</title>
    <description>The latest articles on DEV Community by Rômulo Silva (@rohlacanna).</description>
    <link>https://dev.to/rohlacanna</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%2F830151%2F378c3e83-d5ad-4181-a2ce-57007ac1e40b.jpg</url>
      <title>DEV Community: Rômulo Silva</title>
      <link>https://dev.to/rohlacanna</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rohlacanna"/>
    <language>en</language>
    <item>
      <title>Por que usar @typespecs em seu código Elixir?</title>
      <dc:creator>Rômulo Silva</dc:creator>
      <pubDate>Mon, 27 Feb 2023 14:53:28 +0000</pubDate>
      <link>https://dev.to/rohlacanna/por-que-usar-typespecs-em-seu-codigo-elixir-4id7</link>
      <guid>https://dev.to/rohlacanna/por-que-usar-typespecs-em-seu-codigo-elixir-4id7</guid>
      <description>&lt;p&gt;Elixir é uma linguagem dinâmica e concisa, mas nem sempre é fácil garantir a segurança e a legibilidade do código. Felizmente, Elixir oferece uma ferramenta poderosa para ajudar a resolver esses problemas: os @typespecs.&lt;/p&gt;

&lt;p&gt;Os @typespecs são anotações de tipo opcionais que podem ser adicionadas a funções e módulos em Elixir. Eles permitem especificar os tipos de argumentos e valores de retorno de uma função, tornando mais fácil garantir que seu código esteja correto e fácil de entender.&lt;/p&gt;

&lt;p&gt;Neste artigo, discutiremos o que são os @typespecs, especificações e tipos, suas vantagens, desvantagens, e como eles podem ser usados para tornar o seu código Elixir mais seguro e legível.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que são @typespecs?
&lt;/h2&gt;

&lt;p&gt;Como dito anteriormente, os @typespecs são anotações de tipo opcionais que podem ser adicionadas a funções e módulos em Elixir e usamos ​​para especificar os tipos de argumentos e valores de retorno de uma função.&lt;/p&gt;

&lt;p&gt;Os @typespecs são escritos como comentários acima da função ou módulo que eles descrevem. Por exemplo, a especificação de tipo para uma função que adiciona dois números inteiros seria a seguinte:&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="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, &lt;code&gt;@spec&lt;/code&gt; indica que estamos adicionando uma especificação de tipo para a função &lt;strong&gt;add&lt;/strong&gt;. O tipo de argumentos é especificado como &lt;strong&gt;integer&lt;/strong&gt;, &lt;strong&gt;integer&lt;/strong&gt;, e o tipo de retorno é especificado como &lt;strong&gt;integer&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Especificações e tipos
&lt;/h2&gt;

&lt;p&gt;Os @typespecs também podem ser usados ​​para especificar tipos de valores de retorno que podem ser nil. Vamos ver alguns exemplos a seguir.&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="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;find_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;find_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&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="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, especificamos que a função &lt;strong&gt;find_user&lt;/strong&gt; recebe um argumento do tipo &lt;strong&gt;user_id&lt;/strong&gt; e retorna um map ou &lt;strong&gt;nil&lt;/strong&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="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;
&lt;span class="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;find_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&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;|&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;find_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&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="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse exemplo, definimos dois tipos: &lt;strong&gt;user_id&lt;/strong&gt; e &lt;strong&gt;user&lt;/strong&gt;. O &lt;strong&gt;user_id&lt;/strong&gt; é um alias para o tipo &lt;strong&gt;integer&lt;/strong&gt;, que representa o ID de um usuário. O tipo &lt;strong&gt;user&lt;/strong&gt; é um map que contém informações sobre o usuário, como o ID, o nome, o email e a idade.&lt;/p&gt;

&lt;p&gt;Na especificação de tipo para a função &lt;strong&gt;find_user&lt;/strong&gt;, usamos o tipo &lt;strong&gt;user_id&lt;/strong&gt; como argumento e especificamos que a função pode retornar um map &lt;strong&gt;user&lt;/strong&gt; ou &lt;strong&gt;nil&lt;/strong&gt;. Isso significa que, se a função encontrar um usuário com o ID fornecido, ela retornará um map &lt;strong&gt;user&lt;/strong&gt;. Caso contrário, ela retornará &lt;strong&gt;nil&lt;/strong&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="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;get_names&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="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;get_names&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Tomate"&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="s2"&gt;"Erlang"&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;Nesse exemplo, estamos especificando o tipo de retorno de uma função que retorna uma lista de strings.&lt;/p&gt;

&lt;p&gt;Da mesma forma, você pode especificar o tipo de retorno de uma função que retorna um map da seguinte forma:&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="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;user_info&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;get_user_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;user_info&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;get_user_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&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;name:&lt;/span&gt; &lt;span class="s2"&gt;"Floki"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;4&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;Os @typespecs também podem ser usados para especificar tipos como listas de maps ou maps de listas. 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="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;street:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;city:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;span class="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;addresses:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;get_person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;get_person&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;name:&lt;/span&gt; &lt;span class="s2"&gt;"Floki"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;addresses:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;street:&lt;/span&gt; &lt;span class="s2"&gt;"123 Rua A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;city:&lt;/span&gt; &lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;street:&lt;/span&gt; &lt;span class="s2"&gt;"456 Rua B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;city:&lt;/span&gt; &lt;span class="s2"&gt;"Angra dos Reis"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos também combinar para criar definições de tipos mais complexas. 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="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;circle&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;center:&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;radius:&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;rectangle&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;top_left:&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;bottom_right:&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;circle&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;rectangle&lt;/span&gt;
&lt;span class="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;draw_shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shape&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="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;draw_shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&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;Neste exemplo, criamos definições de tipos para coordenadas, círculos e retângulos e, em seguida, combinamos essas definições de tipos para criar um tipo de forma que pode ser um círculo ou um retângulo. A função &lt;strong&gt;draw_shape&lt;/strong&gt; aceita qualquer tipo de forma e retorna &lt;code&gt;:ok&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O mesmo se aplica quando queremos usar os @typespecs para especificar retornos de funções que podem resultar em erros ou mensagens personalizadas:&lt;/p&gt;

&lt;h2&gt;
  
  
  Retornando erros com @typespecs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@spec&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;user_id&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;integer&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="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="o"&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="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;span class="k"&gt;def&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;user_id&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;case&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&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="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="o"&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="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="no"&gt;nil&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="ss"&gt;:not_found&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;A função &lt;strong&gt;get_user&lt;/strong&gt; retorna uma &lt;strong&gt;tuple&lt;/strong&gt; com &lt;strong&gt;:ok&lt;/strong&gt; e um map contendo as informações do usuário, ou uma tuple com &lt;strong&gt;:error&lt;/strong&gt; e um átomo representando o tipo de erro ocorrido.&lt;/p&gt;

&lt;h4&gt;
  
  
  Retornando um Ecto.Changeset com @typespecs:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_params&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;map&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="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="o"&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="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_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;changeset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;user_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&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&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;: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="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="n"&gt;changeset&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="n"&gt;changeset&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;A função &lt;strong&gt;create_user&lt;/strong&gt; retorna uma tuple com &lt;strong&gt;:ok&lt;/strong&gt; e um map contendo as informações do usuário criado com sucesso, ou uma tuple com &lt;strong&gt;:error&lt;/strong&gt; e um &lt;strong&gt;Ecto.Changeset&lt;/strong&gt; contendo informações sobre os erros de validação ocorridos durante a criação do usuário.&lt;/p&gt;

&lt;h4&gt;
  
  
  Retornando uma mensagem personalizada com @typespecs:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;validate_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;confirm_password&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&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="o"&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="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;validate_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;confirm_password&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;if&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;confirm_password&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:ok&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="s2"&gt;"As senhas não coincidem."&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;Nesse exemplo, a função &lt;strong&gt;validate_password&lt;/strong&gt; retorna &lt;strong&gt;:ok&lt;/strong&gt; caso as senhas informadas sejam iguais, ou uma tuple com &lt;strong&gt;:error&lt;/strong&gt; e uma mensagem personalizada caso as senhas não coincidam.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vantagens dos @typespecs
&lt;/h2&gt;

&lt;p&gt;Os @typespecs têm várias vantagens importantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ajuda a garantir a segurança do seu código&lt;/strong&gt;: Especificando tipos de argumentos e valores de retorno com @typespecs ajudando a garantir que seu código esteja correto e seguro. Ele também ajuda a detectar erros mais cedo no processo de desenvolvimento, antes que possam se transformar em problemas maiores.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Torna seu código mais explícito&lt;/strong&gt;: Especificar tipos de argumentos e valores de retorno com @typespecs torna seu código mais fácil de entender. Isso ajuda a evitar confusão e erros causados por informações ambíguas ou mal documentadas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ajuda na documentação do código&lt;/strong&gt;: Os @typespecs podem ser usados como parte da documentação do seu código. Isso pode tornar sua API mais fácil de entender e usar para outros desenvolvedores que possam trabalhar em seu projeto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Facilita a manutenção do código&lt;/strong&gt;: Os @typespecs podem ajudar a tornar a manutenção do seu código mais fácil e segura. Quando você altera uma função, pode verificar se a alteração afetou os tipos de argumentos ou valores de retorno da função e atualizar a especificação de tipo em conformidade. Isso ajuda a evitar quebras de código e problemas de integração.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Desvantagens dos @typespecs
&lt;/h2&gt;

&lt;p&gt;Embora os @typespecs tenham muitas vantagens, também existem algumas desvantagens a serem consideradas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Podem adicionar complexidade ao código&lt;/strong&gt;: Especificar tipos de argumentos e valores de retorno pode adicionar complexidade ao código. Isso pode tornar o código mais difícil de entender ou ler para desenvolvedores que não estão familiarizados com os @typespecs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Podem aumentar o tempo de desenvolvimento&lt;/strong&gt;: Especificar tipos de argumentos e valores de retorno pode aumentar o tempo de desenvolvimento. Isso ocorre porque você precisa escrever e atualizar as especificações de tipo à medida que escreve o código.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Não podem garantir 100% de segurança&lt;/strong&gt;: Embora os @typespecs possam ajudar a garantir a segurança do seu código, eles não podem garantir 100% de segurança. Você ainda precisa testar e verificar seu código para garantir que ele esteja correto e seguro.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Análise de tipos com Dialyzer
&lt;/h2&gt;

&lt;p&gt;Os @typespecs podem ser usados em conjunto com a ferramenta Dialyzer do Erlang para fornecer uma análise estática de tipos ainda mais poderosa e detectar erros de tipos em tempo de compilação. O Dialyzer é uma ferramenta de análise de tipo estático que pode ser usada para verificar a correção do código Elixir. Ele analisa o código-fonte e os @typespecs em busca de inconsistências e gera avisos e erros se encontrar algum problema.&lt;/p&gt;

&lt;p&gt;Para usar o Dialyzer, você precisa instalar o pacote &lt;strong&gt;dialyxir&lt;/strong&gt; e executar o comando &lt;strong&gt;mix dialyzer&lt;/strong&gt;. E então o Dialyzer irá examinar o seu código e fornecer informações detalhadas sobre quaisquer problemas de tipos encontrados.&lt;/p&gt;

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

&lt;p&gt;Os @typespecs são uma ferramenta poderosa e valiosa para o desenvolvimento de código em Elixir. Eles ajudam a garantir a segurança e a legibilidade do código, facilitam a manutenção e a documentação do código e podem ser usados como parte da documentação da API.&lt;/p&gt;

&lt;p&gt;Embora os @typespecs possam adicionar complexidade ao código e aumentar o tempo de desenvolvimento, os benefícios superam as desvantagens. Se você está desenvolvendo código em Elixir, é altamente recomendável considerar o uso de @typespecs em suas funções e módulos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hexdocs.pm/elixir/main/typespecs.html"&gt;Elixir Typespecs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elixir-lang.org/getting-started/typespecs-and-behaviours.html"&gt;Elixir Typespecs and Behaviours&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.tutorialspoint.com/elixir/elixir_typespecs.htm"&gt;Elixir Typespecs Tutorial&lt;/a&gt;&lt;br&gt;
&lt;a href="//erlang.org/doc/reference_manual/typespec.html"&gt;Erlang Type Specifications and Dialyzer&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Muito obrigado pela leitura até aqui e espero ter ajudado de alguma forma. Tem alguma sugestão ou encontrou algum problema? por favor deixe-me saber. 💜&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>erlang</category>
      <category>typespecs</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Brincando com Ecto.Query</title>
      <dc:creator>Rômulo Silva</dc:creator>
      <pubDate>Sat, 25 Jun 2022 22:58:38 +0000</pubDate>
      <link>https://dev.to/rohlacanna/brincando-com-ectoquery-4paj</link>
      <guid>https://dev.to/rohlacanna/brincando-com-ectoquery-4paj</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Sejam bem-vindos, fico imensamente feliz com seu interesse em aprender um pouco mais sobre o Ecto e suas funcionalidades do modulo &lt;code&gt;Ecto.Query&lt;/code&gt; para construir queries SQL&lt;/p&gt;

&lt;p&gt;Vamos usar o projeto do post &lt;a href="https://dev.to/rohlacanna/introducao-ao-ecto-mh0"&gt;Introdução ao Ecto&lt;/a&gt; para brincarmos um pouco com as queries sql.&lt;/p&gt;

&lt;h6&gt;
  
  
  Recomendo ler o projeto anterior sobre &lt;code&gt;Ecto&lt;/code&gt; para melhor compreensão.
&lt;/h6&gt;

&lt;h2&gt;
  
  
  Schemas utilizado para este projeto:
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Módulo User
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Ecto4noobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;

  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Ecto4noobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Movie&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;belongs_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:movie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Movie&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;h4&gt;
  
  
  Módulo Movie
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Ecto4noobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Movie&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;

  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Ecto4noobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"movies"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:director&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;has_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;User&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;h2&gt;
  
  
  Relação Belongs To/Has Many
&lt;/h2&gt;

&lt;p&gt;Vamos iniciar com dois schemas: User e Movie. Vamos implementar uma relação &lt;code&gt;belongs_to/has_many&lt;/code&gt; entre os dois: Um filme tem vários (has many) usuários e um usuário pertence a (belongs to) um filme.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema Belongs To
&lt;/h3&gt;

&lt;p&gt;Belongs To utiliza a chave estrangeira para tornar o filme associado a um usuário disponível quando executamos a consulta.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema Has Many
&lt;/h3&gt;

&lt;p&gt;Has Many não adiciona dados ao banco de dados por si só. O que ela faz é utilizar uma &lt;code&gt;chave estrangeira&lt;/code&gt; no schema associado (users).&lt;/p&gt;

&lt;h2&gt;
  
  
  Listando os filmes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie&lt;span class="o"&gt;)&lt;/span&gt; |&amp;gt; Repo.all&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fvd3y4785gfnkfevdauix.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%2Fvd3y4785gfnkfevdauix.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se notarmos, veremos que temos a seguinte mensagem: &lt;code&gt;NotLoadAssociation&lt;/code&gt;. Caso a gente queria listar os &lt;code&gt;usuários&lt;/code&gt; juntamente aos &lt;code&gt;filmes&lt;/code&gt;, apenas essa &lt;code&gt;query&lt;/code&gt; não é o suficiente.&lt;/p&gt;

&lt;p&gt;Para carregas as associações, faremos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query &lt;span class="o"&gt;=&lt;/span&gt; from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie, preload: &lt;span class="o"&gt;[&lt;/span&gt;:users]&lt;span class="o"&gt;)&lt;/span&gt; |&amp;gt; Repo.all&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fevy7j0o05m0e145ttxt6.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%2Fevy7j0o05m0e145ttxt6.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplos de query com filtros where:
&lt;/h2&gt;

&lt;p&gt;Buscando os usuários com idade menos que 20.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query &lt;span class="o"&gt;=&lt;/span&gt; from&lt;span class="o"&gt;(&lt;/span&gt;u &lt;span class="k"&gt;in &lt;/span&gt;User, where: u.age &amp;lt; 20&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;U&lt;/code&gt; representa uma linha da tabela &lt;code&gt;User&lt;/code&gt; e em seguida a gente passa a condição que queremos filtrar, que no caso queremos filtrar a idade que for menor que 20.&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%2Fp4shkca9oda8wa5wcpwh.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%2Fp4shkca9oda8wa5wcpwh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Antes de continuarmos vamos aprender um pouco sobre &lt;code&gt;SQL JOIN&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é um JOIN?
&lt;/h3&gt;

&lt;p&gt;Bom, o join combina duas tabelas através de alguma chave ou valor comum entre elas.&lt;/p&gt;

&lt;p&gt;Existem alguns tipos diferentes de JOIN:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;INNER JOIN&lt;/strong&gt;: É um comando que permite a seleção de informações em diferentes tabelas, desde que a informação em questão seja compartilhada por ambas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LEFT JOIN&lt;/strong&gt;: É um comando que retorna todos os registros da tabela à esquerda e os registros correspondentes da tabela à direita.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RIGHT JOIN&lt;/strong&gt;: Ao contrário do LEFT JOIN, o comando RIGHT JOIN retorna todos os dados encontrados na tabela à direita. Porém, se não tiver dados associados entre as tabelas esquerda e direita, ele retorna valores nulos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Usando INNER JOIN
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query &lt;span class="o"&gt;=&lt;/span&gt; 
from&lt;span class="o"&gt;(&lt;/span&gt;u &lt;span class="k"&gt;in &lt;/span&gt;User, 
inner_join: m &lt;span class="k"&gt;in &lt;/span&gt;Movie, 
on: u.movie_id &lt;span class="o"&gt;==&lt;/span&gt; m.id, 
&lt;span class="k"&gt;select&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;m.title, u.name]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, estamos buscando os filmes e o nome do usuário que cada um recebeu. Para isso, começamos a nossa query na tabela &lt;code&gt;User&lt;/code&gt;, depois fazemos um &lt;code&gt;inner_join&lt;/code&gt; na tabela de &lt;code&gt;filmes&lt;/code&gt; e cujo a condição do ID do filme do usuário é igual ao ID do filme. Por fim, a gente faz a seleção dos campos que queremos mostrar.&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%2F4696yjxjgx8ejck3w3z6.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%2F4696yjxjgx8ejck3w3z6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usando LEFT JOIN
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query &lt;span class="o"&gt;=&lt;/span&gt; 
from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie, 
left_join: u &lt;span class="k"&gt;in &lt;/span&gt;User, 
on: u.movie_id &lt;span class="o"&gt;==&lt;/span&gt; m.id, 
where: u.name &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"Floki O Gato"&lt;/span&gt; and m.title &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"Um Sonho de Liberdade"&lt;/span&gt;, 
&lt;span class="k"&gt;select&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;m.title, u.name]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, buscamos filmes que contém o usuário "Floki O Gato". Para isso, começamos a query na tabela Movie, depois fazemos um &lt;code&gt;left_join&lt;/code&gt; na tabela &lt;code&gt;User&lt;/code&gt; e cujo a condição do ID do filme do usuário é igual ao ID do filme eu busco por usuário "Floki O Gato" onde o titulo do filme é "Um Sonho de Liberdade". Por fim, a gente faz a seleção dos campos que queremos mostrar.&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%2Fbz6jmtm26fla3k1ozrl8.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%2Fbz6jmtm26fla3k1ozrl8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usando LEFT EXCLUDING JOIN
&lt;/h3&gt;

&lt;p&gt;Filmes que não tiveram nenhum usuário&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%2Fzzuw220sefqpt3r305ej.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%2Fzzuw220sefqpt3r305ej.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usando RIGHT JOIN
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query &lt;span class="o"&gt;=&lt;/span&gt; 
from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie, 
right_join: u &lt;span class="k"&gt;in &lt;/span&gt;User, 
on: u.movie_id &lt;span class="o"&gt;==&lt;/span&gt; m.id, 
&lt;span class="k"&gt;select&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;m.title, u.name]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, estou buscando os filmes com o usuário que foi recebido.&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%2Fbgwuniclg0sb1tgdkufb.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%2Fbgwuniclg0sb1tgdkufb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usando RIGHT EXCLUDING JOIN
&lt;/h3&gt;

&lt;p&gt;Buscar os filmes com os usuário que cada um recebeu&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query &lt;span class="o"&gt;=&lt;/span&gt; 
from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie, 
right_join: u &lt;span class="k"&gt;in &lt;/span&gt;User, 
on: u.movie_id &lt;span class="o"&gt;==&lt;/span&gt; m.id, 
where: not is_nil&lt;span class="o"&gt;(&lt;/span&gt;u.name&lt;span class="o"&gt;)&lt;/span&gt;, 
&lt;span class="k"&gt;select&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;m.title, u.name]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ffufailpvot7es11uud8c.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%2Ffufailpvot7es11uud8c.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fragment
&lt;/h3&gt;

&lt;p&gt;Forma de chamar funções em SQL puro no Ecto&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query &lt;span class="o"&gt;=&lt;/span&gt; 
from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie, 
&lt;span class="k"&gt;select&lt;/span&gt;: fragment&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"upper(?)"&lt;/span&gt;, m.title&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estamos fazendo uma listagem de títulos de filme em uppercase &lt;code&gt;fragment(upper)&lt;/code&gt; que é uma função do Postgres.&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%2Furn2ynh952abzvuqflgn.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%2Furn2ynh952abzvuqflgn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OU&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;title &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"O Poderoso Chefão"&lt;/span&gt;
query &lt;span class="o"&gt;=&lt;/span&gt; from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie, 
where: m.title &lt;span class="o"&gt;==&lt;/span&gt; ^title, 
&lt;span class="k"&gt;select&lt;/span&gt;: fragment&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"upper(?)"&lt;/span&gt;, m.title&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando queremos colocar um valor de uma variável dentro da querie a gente precisa colocar operador &lt;code&gt;pinar (^)&lt;/code&gt; se não, dará erro de compilação.&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%2Fly88gz3exd4mu1bofeas.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%2Fly88gz3exd4mu1bofeas.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  LIKE
&lt;/h3&gt;

&lt;p&gt;Forma de busca por campo de texto&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;title &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"O"&lt;/span&gt;
query &lt;span class="o"&gt;=&lt;/span&gt; 
from&lt;span class="o"&gt;(&lt;/span&gt;m &lt;span class="k"&gt;in &lt;/span&gt;Movie, 
where: like&lt;span class="o"&gt;(&lt;/span&gt;m.title, ^&lt;span class="s2"&gt;"#{title}%"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, 
&lt;span class="k"&gt;select&lt;/span&gt;: fragment&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"upper(?)"&lt;/span&gt;, m.title&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filtrando títulos de filme que começam com a letra &lt;code&gt;O&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Então, nesse nosso exemplo quero buscar os filmes que começam com O, então eu uso a função do &lt;code&gt;Ecto LIKE&lt;/code&gt; passando o campo de texto que eu quero interpolar e o sinal de pinar, por fim o porcent &lt;code&gt;%&lt;/code&gt; que é para dar &lt;code&gt;match&lt;/code&gt; em qualquer termo.&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%2F1v9y69y9fr8l7aya34uo.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%2F1v9y69y9fr8l7aya34uo.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E é isso! =)&lt;/p&gt;

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

&lt;p&gt;Muito obrigado pela leitura até aqui e espero ter ajudado de alguma forma. Tem alguma sugestão ou encontrou algum problema? por favor deixe-me saber. 💜&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>ecto</category>
      <category>database</category>
      <category>sql</category>
    </item>
    <item>
      <title>Introdução ao Ecto</title>
      <dc:creator>Rômulo Silva</dc:creator>
      <pubDate>Sat, 23 Apr 2022 14:40:20 +0000</pubDate>
      <link>https://dev.to/rohlacanna/introducao-ao-ecto-mh0</link>
      <guid>https://dev.to/rohlacanna/introducao-ao-ecto-mh0</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Sejam bem-vindos à introdução ao Ecto (um projeto onde realizei uma apresentação na &lt;strong&gt;Idopter Labs&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;Esse projeto tem como objetivo auxiliar todos os desenvolvedores iniciantes na programação funcional.&lt;/p&gt;

&lt;p&gt;Fico imensamente feliz com seu interesse em aprender um pouco sobre o Ecto. Espero conseguir fazer você entender todo o básico necessário para que você possa sair daqui já com conhecimento para desenvolver pequenas funcionalidades utilizando Ecto.&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é o Ecto?
&lt;/h1&gt;

&lt;p&gt;Ecto é basicamente uma lib para você interagir com seu banco. Então, podemos dizer que ele é uma camada que vai ficar entre seu banco de dados e sua aplicação. &lt;/p&gt;

&lt;p&gt;Vale ressaltar, que o Ecto não é um "&lt;strong&gt;ORM&lt;/strong&gt;" &lt;em&gt;(Object Relation Mapping)&lt;/em&gt;. Pois, ORM é sobre objetos e Elixir é uma linguagem funcional e não temos objetos em elixir.&lt;/p&gt;

&lt;h1&gt;
  
  
  Arquitetura do Ecto
&lt;/h1&gt;

&lt;p&gt;A biblioteca Ecto é composta por quatro módulos principais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo&lt;/strong&gt;: Este módulo permite conexões com o banco. E é com ele que podemos criar/atualizar/deletar recursos e executar queries. Dito isso, é necessário um adapter específico para o SGBD &lt;em&gt;(sistema de gerenciamento de banco de dados)&lt;/em&gt;. Para conectarmos a banco de dados relacionais &lt;strong&gt;SQL&lt;/strong&gt; usamos a biblioteca &lt;code&gt;Ecto.SQL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema&lt;/strong&gt;: Mapeamento de dados entre código Elixir e estruturas SQL (tabelas, colunas, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query&lt;/strong&gt;: Módulo que permite fazer queries no banco de dados através de uma DSL em Elixir de uma forma mais fácil e segura, evitando &lt;code&gt;SQL Injection&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changeset&lt;/strong&gt;: É um módulo que permite normalizar e validar dados da aplicação.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Operações Básicas
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Cast e Validações
&lt;/h3&gt;

&lt;p&gt;O Changeset recebe uma struct e com isso ele consegue tanto fazer cast de dados para inserir nessa struct como também fazer validações e modificações.&lt;/p&gt;

&lt;p&gt;A função cast pega os parâmetros e tenta fazer o cast nos campos da struct e como segundo argumento temos que definir uma lista de campos para cast.&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="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Ecto4noobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;

  &lt;span class="nv"&gt;@required_params&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="o"&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;changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&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;struct&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cast&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="nv"&gt;@required_params&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;Agora vamos no nosso iex criar um map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; user_params &lt;span class="o"&gt;=&lt;/span&gt; %&lt;span class="o"&gt;{&lt;/span&gt;name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;, email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;, age: 23&lt;span class="o"&gt;}&lt;/span&gt;
%&lt;span class="o"&gt;{&lt;/span&gt;age: 23, email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;, name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E em seguida, vamos criar nosso Changeset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; &lt;span class="nb"&gt;alias &lt;/span&gt;Ecto4noobs.User
Ecto4noobs.User
iex&amp;gt; User.changeset&lt;span class="o"&gt;(&lt;/span&gt;user_params&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;#Ecto.Changeset&amp;lt;&lt;/span&gt;
  action: nil,
  changes: %&lt;span class="o"&gt;{&lt;/span&gt;age: 23, email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;, name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,
  errors: &lt;span class="o"&gt;[]&lt;/span&gt;,
  data: &lt;span class="c"&gt;#Ecto4noobs.User&amp;lt;&amp;gt;,&lt;/span&gt;
  valid?: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora temos um Changeset do Ecto que é uma struct especial que valida os nossos dados, faz cast dos dados e vai ser mandada para o banco.&lt;/p&gt;

&lt;p&gt;Dito isso, vamos criar as validações pela função &lt;code&gt;validate_required&lt;/code&gt; que também recebe uma lista.&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="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Ecto4noobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;

  &lt;span class="nv"&gt;@required_params&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="o"&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;changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&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;struct&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cast&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="nv"&gt;@required_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;validate_required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@required_params&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;Voltando para o nosso iex, vamos remover o name de &lt;code&gt;user_params&lt;/code&gt; e tentar criar o changeset novamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; user_params &lt;span class="o"&gt;=&lt;/span&gt; %&lt;span class="o"&gt;{&lt;/span&gt;email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;, age: 23&lt;span class="o"&gt;}&lt;/span&gt;
%&lt;span class="o"&gt;{&lt;/span&gt;age: 23, email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
iex&amp;gt; User.changeset&lt;span class="o"&gt;(&lt;/span&gt;user_params&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;#Ecto.Changeset&amp;lt;&lt;/span&gt;
  action: nil,
  changes: %&lt;span class="o"&gt;{&lt;/span&gt;age: 23, email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,
  errors: &lt;span class="o"&gt;[&lt;/span&gt;name: &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"can't be blank"&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;validation: :required]&lt;span class="o"&gt;}]&lt;/span&gt;,
  data: &lt;span class="c"&gt;#Ecto4noobs.User&amp;lt;&amp;gt;,&lt;/span&gt;
  valid?: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfeito! Está tudo funcionando, ele nós retorna um &lt;code&gt;error&lt;/code&gt; dizendo que o campo &lt;code&gt;name&lt;/code&gt; não pode ser vazio e um &lt;code&gt;valid?&lt;/code&gt; false!&lt;/p&gt;

&lt;p&gt;Com isso, já podemos partir para a inserção de dados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Escrita de dados
&lt;/h3&gt;

&lt;p&gt;Para fazermos a escrita de dados, vamos utilizar o &lt;code&gt;Ecto.Repo&lt;/code&gt; que define um repositório e mapeia os dados que temos no elixir e o nosso repositório físico que é o nosso banco de dados.&lt;/p&gt;

&lt;p&gt;Vamos ao iex criar nosso map com todos os campos preenchidos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; user_params &lt;span class="o"&gt;=&lt;/span&gt; %&lt;span class="o"&gt;{&lt;/span&gt;name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;, email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;, age: 23&lt;span class="o"&gt;}&lt;/span&gt;
%&lt;span class="o"&gt;{&lt;/span&gt;age: 23, email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;, name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos criar nosso &lt;code&gt;Changeset&lt;/code&gt; e em seguida vamos inserir no nosso banco de dados utilizando &lt;code&gt;Repo.insert/1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; &lt;span class="nb"&gt;alias &lt;/span&gt;Ecto4noobs.User
Ecto4noobs.User
iex&amp;gt; &lt;span class="nb"&gt;alias &lt;/span&gt;Ecto4noobs.Repo
Ecto4noobs.Repo
iex&amp;gt; user_params |&amp;gt; User.changeset&lt;span class="o"&gt;()&lt;/span&gt; |&amp;gt; Repo.insert&lt;span class="o"&gt;()&lt;/span&gt;

15:36:36.977 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4.4ms &lt;span class="nv"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.1ms &lt;span class="nv"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.9ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1294.1ms
INSERT INTO &lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"age"&lt;/span&gt;,&lt;span class="s2"&gt;"email"&lt;/span&gt;,&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; VALUES &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;,&lt;span class="nv"&gt;$2&lt;/span&gt;,&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; RETURNING &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;23, &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;, &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;:ok,
 %Ecto4noobs.User&lt;span class="o"&gt;{&lt;/span&gt;
   __meta__: &lt;span class="c"&gt;#Ecto.Schema.Metadata&amp;lt;:loaded, "users"&amp;gt;,&lt;/span&gt;
   age: 23,
   email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;,
   &lt;span class="nb"&gt;id&lt;/span&gt;: 1,
   name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;
 &lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Leitura de dados
&lt;/h3&gt;

&lt;p&gt;Após ter feito a nossa escrita no banco, agora podemos também fazer a leitura de todos os dados e é bem simples, basta usarmos &lt;code&gt;Repo.all/1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos testar no iex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; Repo.all&lt;span class="o"&gt;(&lt;/span&gt;User&lt;span class="o"&gt;)&lt;/span&gt;

15:41:33.261 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0ms &lt;span class="nv"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.1ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1589.9ms
SELECT u0.&lt;span class="s2"&gt;"id"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"name"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"email"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"age"&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; AS u0 &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  %Ecto4noobs.User&lt;span class="o"&gt;{&lt;/span&gt;
    __meta__: &lt;span class="c"&gt;#Ecto.Schema.Metadata&amp;lt;:loaded, "users"&amp;gt;,&lt;/span&gt;
    age: 23,
    email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;,
    &lt;span class="nb"&gt;id&lt;/span&gt;: 1,
    name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou, podemos fazer a leitura utilizando o &lt;code&gt;Repo.get/2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; Repo.get&lt;span class="o"&gt;(&lt;/span&gt;User, 1&lt;span class="o"&gt;)&lt;/span&gt;

15:42:45.240 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0ms &lt;span class="nv"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.6ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1568.2ms
SELECT u0.&lt;span class="s2"&gt;"id"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"name"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"email"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"age"&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; AS u0 WHERE &lt;span class="o"&gt;(&lt;/span&gt;u0.&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;1]
%Ecto4noobs.User&lt;span class="o"&gt;{&lt;/span&gt;
  __meta__: &lt;span class="c"&gt;#Ecto.Schema.Metadata&amp;lt;:loaded, "users"&amp;gt;,&lt;/span&gt;
  age: 23,
  email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;,
  &lt;span class="nb"&gt;id&lt;/span&gt;: 1,
  name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que fizemos além de passar &lt;code&gt;User&lt;/code&gt; foi passar o &lt;code&gt;ID&lt;/code&gt; do usuário que queremos listar.&lt;/p&gt;

&lt;p&gt;Além das listagens &lt;code&gt;Repo.all/1&lt;/code&gt; e &lt;code&gt;Repo.get/2&lt;/code&gt; também é possível fazer a leitura utilizando um filtro.&lt;/p&gt;

&lt;p&gt;Para isso vamos dizer ao módulo que queremos utilizar suas macros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; require Ecto.Query
Ecto.Query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E agora vamos utilizar o filtro para buscar somente usuários que possui o nome &lt;strong&gt;Floki&lt;/strong&gt; &lt;em&gt;(Eu inseri outro usuário antes de fazer a listagem com filtro)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Voltando para o iex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; Ecto.Query.where&lt;span class="o"&gt;(&lt;/span&gt;User, name: &lt;span class="s2"&gt;"Floki"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; |&amp;gt; Repo.all&lt;span class="o"&gt;()&lt;/span&gt;

15:51:10.119 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.7ms &lt;span class="nv"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.4ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1447.6ms
SELECT u0.&lt;span class="s2"&gt;"id"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"name"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"email"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"age"&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; AS u0 WHERE &lt;span class="o"&gt;(&lt;/span&gt;u0.&lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Floki'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  %Ecto4noobs.User&lt;span class="o"&gt;{&lt;/span&gt;
    __meta__: &lt;span class="c"&gt;#Ecto.Schema.Metadata&amp;lt;:loaded, "users"&amp;gt;,&lt;/span&gt;
    age: 3,
    email: &lt;span class="s2"&gt;"floki@gato.com"&lt;/span&gt;,
    &lt;span class="nb"&gt;id&lt;/span&gt;: 2,
    name: &lt;span class="s2"&gt;"Floki"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Atualização de dados
&lt;/h3&gt;

&lt;p&gt;Para atualizarmos os dados de algum usuário é muito simples!&lt;/p&gt;

&lt;p&gt;Vamos utilizar o &lt;code&gt;Repo.get/2&lt;/code&gt; passando &lt;code&gt;User&lt;/code&gt; e o &lt;code&gt;ID&lt;/code&gt; do usuário que queremos atualizar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Repo.get(User, 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, vamos criar um &lt;code&gt;Changeset&lt;/code&gt; com o campo que queremos fazer a atualização e enviar essa atualização para o banco utilizando &lt;code&gt;Repo.update/1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; Repo.get&lt;span class="o"&gt;(&lt;/span&gt;User, 2&lt;span class="o"&gt;)&lt;/span&gt; |&amp;gt; User.changeset&lt;span class="o"&gt;(&lt;/span&gt;%&lt;span class="o"&gt;{&lt;/span&gt;email: &lt;span class="s2"&gt;"floki@gato.com"&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt; |&amp;gt; Repo.update&lt;span class="o"&gt;()&lt;/span&gt;

15:57:31.334 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.9ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1662.5ms
SELECT u0.&lt;span class="s2"&gt;"id"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"name"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"email"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"age"&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; AS u0 WHERE &lt;span class="o"&gt;(&lt;/span&gt;u0.&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;2]
&lt;span class="o"&gt;{&lt;/span&gt;:ok,
 %Ecto4noobs.User&lt;span class="o"&gt;{&lt;/span&gt;
   __meta__: &lt;span class="c"&gt;#Ecto.Schema.Metadata&amp;lt;:loaded, "users"&amp;gt;,&lt;/span&gt;
   age: 3,
   email: &lt;span class="s2"&gt;"floki@gato.com"&lt;/span&gt;,
   &lt;span class="nb"&gt;id&lt;/span&gt;: 2,
   name: &lt;span class="s2"&gt;"Floki"&lt;/span&gt;
 &lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prontinho! Nosso campo &lt;code&gt;e-mail&lt;/code&gt; foi atualizado com sucesso! :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Remoção de dados
&lt;/h3&gt;

&lt;p&gt;Se você achou fácil atualizar os dados, verá que para remover é muito mais simples!&lt;/p&gt;

&lt;p&gt;Para remover um usuário, vamos utilizar o &lt;code&gt;Repo.get/2&lt;/code&gt; passando &lt;code&gt;User&lt;/code&gt; e o &lt;code&gt;ID&lt;/code&gt; do usuário que queremos deletar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Repo.get(User, 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E por fim, vamos enviar nossa remoção para o banco utilizando &lt;code&gt;Repo.delete/1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; Repo.get&lt;span class="o"&gt;(&lt;/span&gt;User, 1&lt;span class="o"&gt;)&lt;/span&gt; |&amp;gt; Repo.delete&lt;span class="o"&gt;()&lt;/span&gt;

16:02:34.110 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.9ms &lt;span class="nv"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.1ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1438.4ms
SELECT u0.&lt;span class="s2"&gt;"id"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"name"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"email"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"age"&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; AS u0 WHERE &lt;span class="o"&gt;(&lt;/span&gt;u0.&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;1]

16:02:34.114 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2.6ms &lt;span class="nv"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.1ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1440.6ms
DELETE FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; WHERE &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;1]
&lt;span class="o"&gt;{&lt;/span&gt;:ok,
 %Ecto4noobs.User&lt;span class="o"&gt;{&lt;/span&gt;
   __meta__: &lt;span class="c"&gt;#Ecto.Schema.Metadata&amp;lt;:deleted, "users"&amp;gt;,&lt;/span&gt;
   age: 23,
   email: &lt;span class="s2"&gt;"romulo@tomate.com"&lt;/span&gt;,
   &lt;span class="nb"&gt;id&lt;/span&gt;: 1,
   name: &lt;span class="s2"&gt;"Rômulo"&lt;/span&gt;
 &lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para conferir, vamos fazer a leitura de todos os dados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&amp;gt; Repo.all&lt;span class="o"&gt;(&lt;/span&gt;User&lt;span class="o"&gt;)&lt;/span&gt;

16:03:08.243 &lt;span class="o"&gt;[&lt;/span&gt;debug] QUERY OK &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.2ms &lt;span class="nv"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1572.6ms
SELECT u0.&lt;span class="s2"&gt;"id"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"name"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"email"&lt;/span&gt;, u0.&lt;span class="s2"&gt;"age"&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; AS u0 &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  %Ecto4noobs.User&lt;span class="o"&gt;{&lt;/span&gt;
    __meta__: &lt;span class="c"&gt;#Ecto.Schema.Metadata&amp;lt;:loaded, "users"&amp;gt;,&lt;/span&gt;
    age: 3,
    email: &lt;span class="s2"&gt;"floki@gato.com"&lt;/span&gt;,
    &lt;span class="nb"&gt;id&lt;/span&gt;: 2,
    name: &lt;span class="s2"&gt;"Floki"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E é isso! Ficou apenas o usuário &lt;strong&gt;Floki&lt;/strong&gt; :)&lt;/p&gt;

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

&lt;p&gt;Muito obrigado pela leitura até aqui e espero ter ajudado de alguma forma. Tem alguma sugestão ou encontrou algum problema? por favor deixe-me saber. 💜&lt;/p&gt;

&lt;p&gt;Código do projeto no meu &lt;a href="https://github.com/RomuloHe4rt/Introduction_Ecto"&gt;github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>programming</category>
      <category>database</category>
      <category>ecto</category>
    </item>
    <item>
      <title>Ferramentas para desenvolvimento em Elixir</title>
      <dc:creator>Rômulo Silva</dc:creator>
      <pubDate>Sun, 13 Mar 2022 20:45:26 +0000</pubDate>
      <link>https://dev.to/rohlacanna/ferramentas-para-desenvolvimento-em-elixir-27jc</link>
      <guid>https://dev.to/rohlacanna/ferramentas-para-desenvolvimento-em-elixir-27jc</guid>
      <description>&lt;p&gt;Neste guia irei mostrar/ensinar como instalar as ferramentas necessárias para que você consiga desenvolver tranquilamente em Elixir. Recomendo que utilize WSL2 (o que é meu caso) ou então Linux.&lt;/p&gt;

&lt;p&gt;Utilizo a distro Ubuntu 20.04 juntamente com WSL2. Caso, você utilize outra distribuição e tiver problemas, por favor compartilhe conosco sua dúvida.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Como instalar o Elixir?&lt;/strong&gt;&lt;br&gt;
Primeiramente, se você pretende trabalhar com várias versões do &lt;strong&gt;erlang&lt;/strong&gt; ou do &lt;strong&gt;elixir&lt;/strong&gt; ao mesmo tempo o &lt;strong&gt;asdf&lt;/strong&gt; é seu melhor amigo. &lt;strong&gt;ASDF&lt;/strong&gt; nada mais é que um &lt;code&gt;gerenciador de versões&lt;/code&gt; que pode ser usado por várias linguagens de programação, como por exemplo: &lt;strong&gt;Node.js&lt;/strong&gt;, &lt;strong&gt;Ruby&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt; e inclusive o &lt;strong&gt;Elixir&lt;/strong&gt; e o &lt;strong&gt;Erlang&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instalando os pacotes de sistema necessários&lt;/strong&gt;&lt;br&gt;
Para instalarmos o Elixir e o Erlang, precisamos instalar alguns pacotes necessário na nossa máquina.&lt;/p&gt;

&lt;p&gt;Primeiro vamos atualizar nosso sistema:&lt;br&gt;
&lt;code&gt;Isso pode demorar um pouco, caso você tenha acabado de instalar o Ubuntu.&lt;/code&gt;&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instalando os pacotes:&lt;br&gt;
&lt;code&gt;Isso vai demorar bastante, então deixe o comando rodando e aproveite para beber água e comer uma fruta :]&lt;/code&gt;&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;build-essential autoconf m4 libncurses5-dev libwxgtk3.0-gtk3-dev libwxgtk-webview3.0-gtk3-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils libncurses-dev openjdk-11-jdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dependências Erlang opcionais:&lt;/strong&gt;&lt;br&gt;
Se você quiser que o Erlang gere seus documentos ao compilar, ou se precisar do jinterface ou dos aplicativos ODBC, talvez seja necessário instalar algumas dependências extras. O script de compilação Erlang simplesmente os ignora se as dependências não forem atendidas, então tudo isso é opcional.&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;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; libxml2-utils xsltproc fop unixodbc unixodbc unixodbc-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Instalando o asdf&lt;/strong&gt;&lt;br&gt;
Para instalar o asdf, precisamos instalar primeiro o git.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;curl git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se você estiver utilizando o terminal padrão &lt;strong&gt;BASH&lt;/strong&gt;, basta copiar o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/asdf-vm/asdf.git ~/.asdf
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.asdf
git checkout &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git describe &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nt"&gt;--tags&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'\n. $HOME/.asdf/asdf.sh'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'\n. $HOME/.asdf/completions/asdf.bash'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
asdf &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso você utilize o terminal &lt;strong&gt;ZSH&lt;/strong&gt; (assim como eu), copie o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/asdf-vm/asdf.git ~/.asdf
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.asdf
git checkout &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git describe &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nt"&gt;--tags&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'\n. $HOME/.asdf/asdf.sh'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
asdf &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em um novo terminal, instale os plugins Elixir e Erlang:&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="nv"&gt;$ &lt;/span&gt;asdf plugin-add elixir
&lt;span class="nv"&gt;$ &lt;/span&gt;asdf plugin-add erlang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora podemos verificar todas as versões disponíveis do Elixir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf list-all elixir
...
1.13.1-otp-24
1.13.2
1.13.2-otp-22
1.13.2-otp-23
1.13.2-otp-24
1.13.3
1.13.3-otp-22
1.13.3-otp-23
1.13.3-otp-24
main
main-otp-22
main-otp-23
main-otp-24
master
master-otp-21
master-otp-22
master-otp-23
master-otp-24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos instalar a mais recente, que no momento é a &lt;code&gt;1.13.3&lt;/code&gt;&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="nv"&gt;$ &lt;/span&gt;asdf &lt;span class="nb"&gt;install &lt;/span&gt;elixir 1.13.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, precisamos informar ao asdf qual versão do Elixir deve ser usada pela máquina:&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="nv"&gt;$ &lt;/span&gt;asdf global elixir 1.13.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos verificar todas as versões disponíveis do Erlang&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="nv"&gt;$ &lt;/span&gt;asdf list-all erlang
...
24.0.2
24.0.3
24.0.4
24.0.5
24.0.6
24.1
24.1.1
24.1.2
24.1.3
24.1.4
24.1.5
24.1.6
24.1.7
24.2
24.2.1
24.2.2
24.3
25.0-rc1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eu instalei na minha máquina a versão 24.2.2. Mas, sinta-se à vontade para instalar outra versão.&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="nv"&gt;$ &lt;/span&gt;asdf &lt;span class="nb"&gt;install &lt;/span&gt;erlang 24.2.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E por fim, vamos informar novamente ao asdf qual versão deve ser usada pela máquina:&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="nv"&gt;$ &lt;/span&gt;asdf global erlang 24.2.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Instalando o Phoenix&lt;/strong&gt;&lt;br&gt;
Comando para instalar o Phoenix:&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="nv"&gt;$ &lt;/span&gt;mix archive.install hex phx_new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Instalando o PostgreSQL com Docker&lt;/strong&gt;&lt;br&gt;
O PostgreSQL é um servidor de banco de dados relacional. O Phoenix configura os aplicativos para usá-lo por padrão, mas caso você queira mudar, basta passar a flag &lt;code&gt;--database&lt;/code&gt; ao criar um aplicativo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instalação do Docker:&lt;/strong&gt;&lt;br&gt;
O Docker é uma ferramenta que nos permite pular as etapas chatas de configuração de serviços para nossa aplicação. Além disso, ele permite reaproveitarmos o Kernel da máquina hospedeira entre vários serviços executados simultaneamente, conhecidos como containers.&lt;/p&gt;

&lt;p&gt;Para instalar o Docker, sugiro esse link: &lt;a href="https://docs.docker.com/desktop/windows/wsl/"&gt;Docker Desktop WSL 2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de instalar o Docker e abrir o software você já está pronto para continuar. &lt;/p&gt;

&lt;p&gt;Para verificar que o Docker foi instalado corretamente, em uma nova janela do terminal execute:&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="nv"&gt;$ &lt;/span&gt;docker version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o Docker instalado na sua máquina, basta rodar o seguinte comando no seu terminal para instalar o postgres:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Os dados para autenticação no banco nesse caso serão:&lt;br&gt;
usuário: postgres&lt;br&gt;
senha: postgres&lt;/code&gt;&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="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; postgres &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 &lt;span class="nt"&gt;-d&lt;/span&gt; postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lembrando que caso você esteja usando Ubuntu/Debian é necessário usar &lt;strong&gt;sudo&lt;/strong&gt; antes do comando.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instalação padrão (Sem Docker)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para instalar o PostgreSQL na sua máquina basta escolher a opção adequada para o seu sistema operacional e fazer a instalação como recomendado:&lt;br&gt;
&lt;a href="https://www.postgresql.org/download/"&gt;PostgreSQL Downloads&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Caso queira, você pode seguir os passos listados aqui de forma mais simples.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linux Ubuntu 20.04&lt;/strong&gt;&lt;br&gt;
Para a instalação no Linux Ubuntu rode os seguintes comandos separadamente:&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;sudo &lt;/span&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" &amp;gt; /etc/apt/sources.list.d/pgdg.list'&lt;/span&gt;

wget &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; - https://www.postgresql.org/media/keys/ACCC4CF8.asc | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;br&gt;
Para o Windows a única forma de instalação disponível é através do instalador. Você pode realizar o download através desse link:&lt;br&gt;
&lt;a href="https://www.enterprisedb.com/postgresql-tutorial-resources-training?cid=437"&gt;PostgreSQL Tutorials, Resources and Training | EDB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configurações para o Visual Studio Code&lt;/strong&gt;&lt;br&gt;
Para o Visual Studio Code, precisaremos apenas instalar algumas extensões.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ElixirLS&lt;/strong&gt;&lt;br&gt;
A extensão a ser instalada é a ElixirLS, que também pode ser acessada diretamente pelo link:&lt;br&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=JakeBecker.elixir-ls"&gt;ElixirLS: Elixir support and debugger&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instalando o Insomnia&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Antes de instalar o Insomnia, é importante ressaltar que ele é compatível somente com sistemas 64-bit. Mas você pode usar o &lt;a href="https://www.postman.com/"&gt;Postman&lt;/a&gt; que é bastante semelhante ao Insomnia e é acessado diretamente pelo navegador.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;br&gt;
Para instalar o Insomnia no Windows, basta fazer o &lt;a href="https://updates.insomnia.rest/downloads/windows/latest?app=com.insomnia.app&amp;amp;source=website"&gt;download do instalador&lt;/a&gt; e concluir a instalação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;br&gt;
Para instalar o Insomnia no Linux, você pode usar o snapd que é semelhante à um gerenciador de pacotes. Com ele podemos instalar diversos aplicativos com um único comando.&lt;/p&gt;

&lt;p&gt;Para verificar se você possui ou não o snapd instalado, pode checar nesse link: &lt;a href="https://snapcraft.io/docs/installing-snapd"&gt;Installing snapd&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se a distribuição Linux instalada na sua máquina estiver na seção &lt;strong&gt;Distributions without snap pre-installed&lt;/strong&gt; significa que você não possui o snapd instalado. Para instalar basta clicar no link com o nome da sua distribuição e você irá para uma página com o passo a passo para a instalação. &lt;/p&gt;

&lt;p&gt;Com o snapd instalado, tudo que você precisa fazer é rodar o seguinte comando no seu terminal:&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;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;insomnia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;br&gt;
Muito obrigado pela leitura até aqui e espero ter ajudado de alguma forma. Tem alguma sugestão ou encontrou algum problema? por favor deixe-me saber. 💜&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>postgres</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
