<?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: Alexandre</title>
    <description>The latest articles on DEV Community by Alexandre (@xandekk).</description>
    <link>https://dev.to/xandekk</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%2F972642%2F8c370e43-5909-4031-8abf-b3843b3e9a21.png</url>
      <title>DEV Community: Alexandre</title>
      <link>https://dev.to/xandekk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xandekk"/>
    <language>en</language>
    <item>
      <title>Criando plug-in em c para gimp</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Mon, 01 May 2023 19:20:07 +0000</pubDate>
      <link>https://dev.to/xandekk/criando-plug-in-em-c-para-gimp-27cd</link>
      <guid>https://dev.to/xandekk/criando-plug-in-em-c-para-gimp-27cd</guid>
      <description>&lt;p&gt;Bem, hoje vamos criar um plug-in em c para automatizar algumas tarefas repetitivas e chatas.&lt;/p&gt;

&lt;p&gt;Antes de começar fazer o código, é necessário instalar o &lt;code&gt;gimptool&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Então, vamos instalar ele.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando o gimptool
&lt;/h2&gt;

&lt;p&gt;Antes de continuarmos, tenho que esclarecer que eu vou fazer isso em Linux, pois eu não uso o Window, então se você não sabe onde achar o &lt;code&gt;gimptool&lt;/code&gt; para Window.&lt;/p&gt;

&lt;p&gt;Mas não se preocupe, eu vou te ajudar onde pode estar esse &lt;code&gt;gimptool&lt;/code&gt; no Window, de acordo com &lt;a href="//strontic.github.io"&gt;strontic&lt;/a&gt;, Ele diz que o arquivo pode está localizado no &lt;code&gt;C:\program files\GIMP 2\bin\gimptool-2.0.exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Então, se você conseguiu localizar o arquivo, com isso, você já pode partir para a criação de plug-in.&lt;/p&gt;

&lt;p&gt;Agora vamos instalar o Gimptool no Linux, no caso Ubuntu/Debian.&lt;/p&gt;

&lt;p&gt;Basta ir ao terminal executar o comando: &lt;code&gt;sudo apt install libgimp2.0-dev&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pronto, é só isso, agora vamos criar um plug-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando um plug-in
&lt;/h2&gt;

&lt;p&gt;Beleza, antes de criar o plug-in, eu vou explicar o eu vou fazer.&lt;/p&gt;

&lt;p&gt;Para não dificultar o processo de aprendizado, eu vou fazer um plug-in bem simples, mas bem simples mesmo.&lt;/p&gt;

&lt;p&gt;É basicamente colocar uma guide(guia).&lt;/p&gt;

&lt;p&gt;Se você não sabe o que é guide. Abra o gimp e vá ao menu "Image" Ou "Imagem", se estiver português, e verá ele aí.&lt;/p&gt;

&lt;p&gt;Passando o mouse em cima, você verá 4 opções.&lt;/p&gt;

&lt;p&gt;Aqui está uma captura de tela.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Nssi8FL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2zda2svgbugrhh7hgem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Nssi8FL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2zda2svgbugrhh7hgem.png" alt="Localização do guide" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicando na primeira opção, vai aparecer uma tela para escolher a direção e inserir um valor da posição da guia.&lt;/p&gt;

&lt;p&gt;Então, colocando na direção vertical e posição 50%, vai aparecer uma linha azul no meio da imagem, por exemplo, nessa captura de tela.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W2E1RRJ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18oghu9jxwdqcaob10v4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W2E1RRJ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18oghu9jxwdqcaob10v4.png" alt="A linha azul de guia" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eu quero automatizar isso, pois é chato fica abrindo a telinha e inserindo os valores.&lt;/p&gt;

&lt;p&gt;Então, primeiro, vamos criar um arquivo chamado &lt;code&gt;add_guias.c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Eu vou colocar o código inteiro logo de vez para fazer um teste, e então, depois vou explicando ao pouco.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;libgimp/gimp.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="n"&gt;nparams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GimpParam&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nreturn_vals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;GimpParam&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;return_vals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;GimpPlugInInfo&lt;/span&gt; &lt;span class="n"&gt;PLUG_IN_INFO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// init&lt;/span&gt;
    &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// quit&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;GimpParamDef&lt;/span&gt; &lt;span class="n"&gt;args&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="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;GIMP_PDB_INT32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de variável&lt;/span&gt;
      &lt;span class="s"&gt;"run-mode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome da variável&lt;/span&gt;
      &lt;span class="s"&gt;"Run mode"&lt;/span&gt; &lt;span class="c1"&gt;// Descrição da variável&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;GIMP_PDB_IMAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de variável&lt;/span&gt;
      &lt;span class="s"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome da variável&lt;/span&gt;
      &lt;span class="s"&gt;"Input image"&lt;/span&gt; &lt;span class="c1"&gt;// Descrição da variável&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;GIMP_PDB_DRAWABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de variável&lt;/span&gt;
      &lt;span class="s"&gt;"drawable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome da variável&lt;/span&gt;
      &lt;span class="s"&gt;"Input drawable"&lt;/span&gt; &lt;span class="c1"&gt;// Descrição da variável&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="n"&gt;gimp_install_procedure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"plug-in-add_guias"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome do procedure&lt;/span&gt;
    &lt;span class="s"&gt;"Adiciona guia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Uma pequena descrição do que o procedure faz&lt;/span&gt;
    &lt;span class="s"&gt;"Ele adiciona uma guia no meio da imagem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Uma descrição completa&lt;/span&gt;
    &lt;span class="s"&gt;"Alexandre dos Santos Alves"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Seu nome&lt;/span&gt;
    &lt;span class="s"&gt;"Copyright Alexandre"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Licença&lt;/span&gt;
    &lt;span class="s"&gt;"2023"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Ano que foi criado&lt;/span&gt;
    &lt;span class="s"&gt;"_Adicona Guia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome que vai aparece no menu&lt;/span&gt;
    &lt;span class="s"&gt;"RGB*, GRAY*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de imagem que o procedure vai trabalhar&lt;/span&gt;
    &lt;span class="n"&gt;GIMP_PLUGIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de procedure&lt;/span&gt;
    &lt;span class="n"&gt;G_N_ELEMENTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Tamanho do parâmetro&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tamanho do retorno&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// o parâmetro do procedure&lt;/span&gt;
    &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// o retorno do procedure.&lt;/span&gt;

  &lt;span class="n"&gt;gimp_plugin_menu_register&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"plug-in-add_guias"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                               &lt;span class="s"&gt;"&amp;lt;Image&amp;gt;/Tools/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt;      &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt;              &lt;span class="n"&gt;nparams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GimpParam&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt;             &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nreturn_vals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;GimpParam&lt;/span&gt;       &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;return_vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// A variável que vai ser retornado&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;GimpParam&lt;/span&gt;  &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;GimpPDBStatusType&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GIMP_PDB_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="n"&gt;GimpRunMode&lt;/span&gt;       &lt;span class="n"&gt;run_mode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;GimpDrawable&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;drawable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* Definindo valores de saída obrigatórios    */&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nreturn_vals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;return_vals&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* É obrigatório isso */&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GIMP_PDB_STATUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;run_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_int32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;drawable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gimp_drawable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_drawable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;gdouble&lt;/span&gt; &lt;span class="n"&gt;metade_do_tamanho_da_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gimp_image_width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;gimp_image_add_vguide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metade_do_tamanho_da_image&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;gimp_displays_flush&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;MAIN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com esse código, copie e cole no arquivo e execute o comando no qual o arquivo está localizado.&lt;/p&gt;

&lt;p&gt;Se for Window, &lt;code&gt;C:\program files\GIMP 2\bin\gimptool-2.0.exe --install add_guias.c&lt;/code&gt;.&lt;br&gt;
Se for Linux, &lt;code&gt;gimptool-2.0 --install add_guias.c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Se por acaso, aparecer isso aqui embaixo, pode ignorar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;add_guias.c:92:2: warning: ‘gimp_drawable_get’ is deprecated: Use &lt;span class="s1"&gt;'gimp_drawable_get_buffer'&lt;/span&gt; instead &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-Wdeprecated-declarations&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
   92 |  drawable &lt;span class="o"&gt;=&lt;/span&gt; gimp_drawable_get&lt;span class="o"&gt;(&lt;/span&gt;param[2].data.d_drawable&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      |  ^~~~~~~~
In file included from /usr/include/gimp-2.0/libgimp/gimp.h:41,
                 from add_guias.c:1:
/usr/include/gimp-2.0/libgimp/gimpdrawable.h:52:16: note: declared here
   52 | GimpDrawable &lt;span class="k"&gt;*&lt;/span&gt; gimp_drawable_get                    &lt;span class="o"&gt;(&lt;/span&gt;gint32         drawable_ID&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      |                ^~~~~~~~~~~~~~~~~
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se não houver erro, além desse aviso, agora, ele vai aparece no Gimp, então feche o Gimp e abra novamente e você verá no menu Tools(Ferramentas) um item com nome Adiciona Guia.&lt;/p&gt;

&lt;p&gt;Crie uma nova imagem e clique nele para ver o que acontece.&lt;/p&gt;

&lt;p&gt;Bem, Se apareceu a linha azul, então ele funcionou, se não, aí é com você para resolver.&lt;/p&gt;

&lt;p&gt;Mentira, comente no comentário, o problema.&lt;/p&gt;

&lt;p&gt;Mas, agora, vamos entender o código.&lt;/p&gt;

&lt;p&gt;Na primeira linha, estamos incluindo uma biblioteca essencial para construção do plug-in, então não tem muito o que explicar sobre isso.&lt;/p&gt;

&lt;p&gt;Em baixo disso, podemos ver duas funções, &lt;code&gt;query&lt;/code&gt; e &lt;code&gt;run&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="n"&gt;nparams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GimpParam&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nreturn_vals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;GimpParam&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;return_vals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;GimpPlugInInfo&lt;/span&gt; &lt;span class="n"&gt;PLUG_IN_INFO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// init&lt;/span&gt;
    &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// quit&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Mas antes de explicar essas funções, vamos pular essa parte e ver a variável &lt;code&gt;PLUG_IN_INFO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Essa variável pode guardar 4 valores.&lt;/p&gt;

&lt;p&gt;Mas o que são esses valores?&lt;/p&gt;

&lt;p&gt;São funções que o Gimp vai chamar.&lt;/p&gt;

&lt;p&gt;Ou seja, o primeiro valor é uma função que vai ser chamado durante a inicialização do Gimp, no meu caso, eu coloquei &lt;code&gt;NULL&lt;/code&gt;, pois não quero fazer nada durante a inicialização.&lt;/p&gt;

&lt;p&gt;O segundo é &lt;code&gt;quit&lt;/code&gt;, que vai ser chamado durante  o fechamento do Gimp, que no meu caso, está &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esses dois valores que citei, são opcionais, ou seja, não é necessário ter uma função, basta colocar &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora os dois próximos que vou citar são obrigatórios.&lt;/p&gt;

&lt;p&gt;O terceiro é &lt;code&gt;query&lt;/code&gt;, não sei muito o que explicar sobre isso, pois a documentação não diz muito sobre isso, mas no meu entendimento, suponho que é usado para instalar o plug-in, mas vamos tenta entender mais, quando estivemos na dentro função &lt;code&gt;query()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O quarto e último é &lt;code&gt;run&lt;/code&gt;, é peça central do código, pois ele vai ser rodado, quando for chamado, seja pelo menu, ou pelo script fu, ou Python fu.&lt;/p&gt;

&lt;p&gt;Agora, sabendo disso, vamos partir para aquelas duas funções criada para entender os parâmetros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome do plug-in&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="n"&gt;nparams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Quantidade de parâmetro&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GimpParam&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// O parâmetro do plug-in&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nreturn_vals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Quantidade de retorno&lt;/span&gt;
    &lt;span class="n"&gt;GimpParam&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;return_vals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// O retorno do plug-in&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não tem muito que o explicar sobre o parâmetro do &lt;code&gt;query&lt;/code&gt;, então vamos para &lt;code&gt;run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O primeiro parâmetro é o nome do plug-in.&lt;br&gt;
O segundo é a quantidade de parâmetro.&lt;br&gt;
O terceiro é o parâmetro do plug-in.&lt;br&gt;
O quarto é a quantidade de retorno.&lt;br&gt;
O quinto é o retorno do plug-in.&lt;/p&gt;

&lt;p&gt;Beleza, sabendo quais são os parâmetros.&lt;/p&gt;

&lt;p&gt;Agora, vamos entender ver o que dentro da função &lt;code&gt;query(void)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;GimpParamDef&lt;/span&gt; &lt;span class="n"&gt;args&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="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;GIMP_PDB_INT32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de variável&lt;/span&gt;
      &lt;span class="s"&gt;"run-mode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome da variável&lt;/span&gt;
      &lt;span class="s"&gt;"Run mode"&lt;/span&gt; &lt;span class="c1"&gt;// Descrição da variável&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;GIMP_PDB_IMAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de variável&lt;/span&gt;
      &lt;span class="s"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome da variável&lt;/span&gt;
      &lt;span class="s"&gt;"Input image"&lt;/span&gt; &lt;span class="c1"&gt;// Descrição da variável&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;GIMP_PDB_DRAWABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de variável&lt;/span&gt;
      &lt;span class="s"&gt;"drawable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome da variável&lt;/span&gt;
      &lt;span class="s"&gt;"Input drawable"&lt;/span&gt; &lt;span class="c1"&gt;// Descrição da variável&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="n"&gt;gimp_install_procedure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"plug-in-add_guias"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome do procedure&lt;/span&gt;
    &lt;span class="s"&gt;"Adiciona guia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Uma pequena descrição do que o procedure faz&lt;/span&gt;
    &lt;span class="s"&gt;"Ele adiciona uma guia no meio da imagem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Uma descrição completa&lt;/span&gt;
    &lt;span class="s"&gt;"Alexandre dos Santos Alves"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Seu nome&lt;/span&gt;
    &lt;span class="s"&gt;"Copyright Alexandre"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Licença&lt;/span&gt;
    &lt;span class="s"&gt;"2023"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Ano que foi criado&lt;/span&gt;
    &lt;span class="s"&gt;"_Adicona Guia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome que vai aparece no menu&lt;/span&gt;
    &lt;span class="s"&gt;"RGB*, GRAY*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de imagem que o procedure vai trabalhar&lt;/span&gt;
    &lt;span class="n"&gt;GIMP_PLUGIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tipo de procedure&lt;/span&gt;
    &lt;span class="n"&gt;G_N_ELEMENTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Tamanho do parâmetro&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tamanho do retorno&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// o parâmetro do procedure&lt;/span&gt;
    &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// o retorno do procedure.&lt;/span&gt;

  &lt;span class="n"&gt;gimp_plugin_menu_register&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"plug-in-add_guias"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// nome do plug-in&lt;/span&gt;
                               &lt;span class="s"&gt;"&amp;lt;Image&amp;gt;/Tools/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Localização dele no menu&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Primeiro, declaramos uma variável &lt;code&gt;static GimpParamDef args[]&lt;/code&gt;, ela possibilita saber quais são os valores do parâmetro que o plug-in recebe.&lt;/p&gt;

&lt;p&gt;No nosso caso, vamos apenas manter o padrão, que são &lt;code&gt;run-mode&lt;/code&gt;, &lt;code&gt;image&lt;/code&gt; e &lt;code&gt;drawable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mas se por acaso, seu plug-in precisa de mais valores, eu vou colocar uma lista de cada tipo de variável para facilitar para você.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipo de variável&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_INT32&lt;/td&gt;
&lt;td&gt;32-bit integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_INT16&lt;/td&gt;
&lt;td&gt;16-bit integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_INT8&lt;/td&gt;
&lt;td&gt;8-bit integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_FLOAT&lt;/td&gt;
&lt;td&gt;Float&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_STRING&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_INT32ARRAY&lt;/td&gt;
&lt;td&gt;Array of INT32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_INT16ARRAY&lt;/td&gt;
&lt;td&gt;Array of INT16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_INT8ARRAY&lt;/td&gt;
&lt;td&gt;Array of INT8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_FLOATARRAY&lt;/td&gt;
&lt;td&gt;Array of floats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_STRINGARRAY&lt;/td&gt;
&lt;td&gt;Array of strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_COLOR&lt;/td&gt;
&lt;td&gt;Color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_ITEM&lt;/td&gt;
&lt;td&gt;Item ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_DISPLAY&lt;/td&gt;
&lt;td&gt;Display ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_IMAGE&lt;/td&gt;
&lt;td&gt;Image ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_LAYER&lt;/td&gt;
&lt;td&gt;Layer ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_CHANNEL&lt;/td&gt;
&lt;td&gt;Channel ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_DRAWABLE&lt;/td&gt;
&lt;td&gt;Drawable ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_SELECTION&lt;/td&gt;
&lt;td&gt;Selection ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_COLORARRAY&lt;/td&gt;
&lt;td&gt;Array of colors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_VECTORS&lt;/td&gt;
&lt;td&gt;Vectors (psath) ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_PARASITE&lt;/td&gt;
&lt;td&gt;Parasite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_STATUS&lt;/td&gt;
&lt;td&gt;Procedure return status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIMP_PDB_END&lt;/td&gt;
&lt;td&gt;Marker for last enum value&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Beleza, Já entendemos sobre o &lt;code&gt;args[]&lt;/code&gt;, agora vamos para função que estamos chamando &lt;code&gt;gimp_install_procedure&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Não tem muito o que explicar, pois se você ler o comentário ao lado do parâmetro, já dá pra ter uma noção, mas o que ele basicamente faz é instalar o plug-in no gimp.&lt;/p&gt;

&lt;p&gt;Então, vamos para outra função que é &lt;code&gt;gimp_plugin_menu_register&lt;/code&gt;. Como o nome diz, ele vai registrar o plug-in no Menu, que no nosso caso, vai ser colocado no &lt;code&gt;Tools&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Aqui nós terminamos a função &lt;code&gt;query()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos para função &lt;code&gt;run()&lt;/code&gt;, por ser um código um pouco grande, eu vou colocar a explicação dentro do código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt;      &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt;              &lt;span class="n"&gt;nparams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GimpParam&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt;             &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nreturn_vals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;GimpParam&lt;/span&gt;       &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;return_vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// A variável que vai ser retornado&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;GimpParam&lt;/span&gt;  &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Como o nome diz é o status&lt;/span&gt;
    &lt;span class="n"&gt;GimpPDBStatusType&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GIMP_PDB_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="c1"&gt;// O run_mode é usado para saber se estar no modo interativo ou não&lt;/span&gt;
    &lt;span class="c1"&gt;// Não irei explicar isso nesse blog&lt;/span&gt;
    &lt;span class="n"&gt;GimpRunMode&lt;/span&gt;       &lt;span class="n"&gt;run_mode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Variável que, por padrão, é o layer(camada) atual.&lt;/span&gt;
    &lt;span class="n"&gt;GimpDrawable&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;drawable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* Definindo valores de saída obrigatórios    */&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nreturn_vals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// definindo o tamanho da variável values&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;return_vals&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* É obrigatório isso */&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GIMP_PDB_STATUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Aqui temos uma forma de pegar os valores passados no parâmetro&lt;/span&gt;
    &lt;span class="c1"&gt;// Eu vou colocar lista de tipos de variáveis abaixo fora do código&lt;/span&gt;
    &lt;span class="c1"&gt;// Sobre o índices da variável 'param', ele está na mesma ordem&lt;/span&gt;
    &lt;span class="c1"&gt;// que você declarou na função 'query' da variável 'args'&lt;/span&gt;
    &lt;span class="n"&gt;run_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_int32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;gint&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;drawable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gimp_drawable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d_drawable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Agora, a partir daqui, são os códigos que você pode fazer&lt;/span&gt;
    &lt;span class="c1"&gt;// Aqui estamos pegando a metade do tamanho da imagem&lt;/span&gt;
    &lt;span class="c1"&gt;// Para poder colocar a guia no meio&lt;/span&gt;
    &lt;span class="n"&gt;gdouble&lt;/span&gt; &lt;span class="n"&gt;metade_do_tamanho_da_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gimp_image_width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// essa função coloca a guia, primeiro parâmetro é a imagem&lt;/span&gt;
    &lt;span class="c1"&gt;// o segundo é a posição dessa guia&lt;/span&gt;
    &lt;span class="n"&gt;gimp_image_add_vguide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metade_do_tamanho_da_image&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Essa função serve para atualizar o que você fez no código,&lt;/span&gt;
    &lt;span class="c1"&gt;// mas não é necessário para o nosso caso,&lt;/span&gt;
        &lt;span class="c1"&gt;// Não estamos alterando a imagem&lt;/span&gt;
    &lt;span class="n"&gt;gimp_displays_flush&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipos de variáveis&lt;/th&gt;
&lt;th&gt;membro&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_int32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint16&lt;/td&gt;
&lt;td&gt;d_int16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;guint8&lt;/td&gt;
&lt;td&gt;d_int8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gdouble&lt;/td&gt;
&lt;td&gt;d_float&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gchar&lt;/td&gt;
&lt;td&gt;d_string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_int32array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint16&lt;/td&gt;
&lt;td&gt;d_int16array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;guint8&lt;/td&gt;
&lt;td&gt;d_int8array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gdouble&lt;/td&gt;
&lt;td&gt;d_floatarray&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gchar&lt;/td&gt;
&lt;td&gt;d_stringarray&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GimpRGB&lt;/td&gt;
&lt;td&gt;d_colorarray&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GimpRGB&lt;/td&gt;
&lt;td&gt;d_color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_display&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_layer_mask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_channel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_drawable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_selection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_vectors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GimpParasite&lt;/td&gt;
&lt;td&gt;d_parasite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gint32&lt;/td&gt;
&lt;td&gt;d_tattoo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GimpPDBStatusType&lt;/td&gt;
&lt;td&gt;d_status&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Se você não entendeu essa lista ou não sabe usá-la, basta fazer assim &lt;code&gt;param[i].data.membro&lt;/code&gt;, troque o membro para um item da lista.&lt;/p&gt;

&lt;p&gt;E por último, temos que colocar o &lt;code&gt;MAIN()&lt;/code&gt;, é obrigatório que tenha isso, e que fique no final do arquivo.&lt;/p&gt;

&lt;p&gt;Pronto, com isso, você tem a base para construir um plug-in por si próprio, só que não, pois você ainda não sabe quais são os métodos disponíveis no Gimp.&lt;/p&gt;

&lt;p&gt;Aqui está a documentação do &lt;a href="https://developer.gimp.org/api/3.0/libgimp/index.html"&gt;Gimp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Agora, sim, podemos terminar aqui.&lt;/p&gt;

&lt;p&gt;Bem, então é isso e tchau!&lt;/p&gt;

</description>
      <category>gimp</category>
      <category>c</category>
      <category>automatizacão</category>
      <category>plugin</category>
    </item>
    <item>
      <title>O básico de Action Cable em Rails 7</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Sun, 18 Dec 2022 18:56:50 +0000</pubDate>
      <link>https://dev.to/xandekk/o-basico-de-action-cable-em-rails-7-13h4</link>
      <guid>https://dev.to/xandekk/o-basico-de-action-cable-em-rails-7-13h4</guid>
      <description>&lt;p&gt;Se você quer criar um chat em tempo real, ou então criar um joguinho multiplayer, então para fazer em Rails, será necessário usar o Action Cable.&lt;/p&gt;

&lt;p&gt;Então, vamos lá.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Action Cable?
&lt;/h2&gt;

&lt;p&gt;Action Cable integra perfeitamente com WebSockets com o resto da sua aplicação Rails. Isso permite que recursos em tempo real sejam escritos em Ruby no mesmo estilo da sua aplicação, enquanto ainda é performático e escalável. Isso é uma oferecimento full-stack que providencia o framework Javascript do client-side e framework Ruby do server-side.&lt;/p&gt;

&lt;p&gt;Agora, que nós sabe o que é Action Cable, vamos entender algumas termologias.&lt;/p&gt;

&lt;h2&gt;
  
  
  Termologias
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Connections ou Conexões
&lt;/h3&gt;

&lt;p&gt;Connections (Conexões) formam a base do relacionamento cliente-servidor. Um único servidor Action Cable pode lidar com várias instâncias de conexão. Um único usuário pode ter vários WebSockets abertos para seu aplicativo se usar várias abas do navegador ou dispositivos diferentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consumers ou consumidores
&lt;/h3&gt;

&lt;p&gt;O cliente de uma conexão WebSocket é chamado de consumer (consumidor). Em Action Cable, o consumer é criado pelo framework javascript do client-side&lt;/p&gt;

&lt;h3&gt;
  
  
  Channels ou Canais
&lt;/h3&gt;

&lt;p&gt;Cada consumer pode, por sua vez, assinar vários channels.&lt;br&gt;
Cada canal encapsula uma unidade lógica de trabalho, similar o que controller faz no típico MVC. Por exemplo, você pode ter um &lt;code&gt;ChatChannel&lt;/code&gt; e um &lt;code&gt;PresencaChannel&lt;/code&gt; e um consumer pode assinar um ou ambos canais. No minimo, o consumer deve assinar pelo menos um canal.&lt;/p&gt;
&lt;h3&gt;
  
  
  Subscribers ou Assinantes
&lt;/h3&gt;

&lt;p&gt;Quando o consumer está assinado em um channel, ele pode agir como um subscriber (assinante). A conexão entre o subscriber e o channel é, surprise-surprise, chamado de assinatura. Um consumer pode agir como um subscriber de um determinado channel quantas vezes quiser. Por exemplo, um consumer pode assinar várias sala de conversa ao mesmo tempo.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pub/Sub
&lt;/h3&gt;

&lt;p&gt;Pub/Sub ou Publish-Subscribe (Publicar-Assinar) refere-se a uma paradigma de fila de messagens por meio do qual os remetentes de informações (publishers), enviam dados apara uma classe abstrata de destinatários (subscribers), sem especificar os destinatários individuais. Action Cable usa essa abordagem para comunicar entre o servidor e vários clientes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Broadcastings ou Transmissões
&lt;/h3&gt;

&lt;p&gt;Um broadcasting é um link pub/sub em que qualquer coisa transmitida pelo broadcaster é enviada diretamente para os subscribers do channel que estão transmitindo essa chamada broadcasting. Cada canal pode transmitir zero ou mais broadcastings.&lt;/p&gt;

&lt;p&gt;Tendo o conhecimento das termologias, vamos criar uma aplicação.&lt;/p&gt;
&lt;h2&gt;
  
  
  Criando uma aplicação
&lt;/h2&gt;

&lt;p&gt;O aplicativo que vou criar é um chat.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new chat
&lt;span class="nb"&gt;cd &lt;/span&gt;chat
rails g controller Chat index
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coloque a rota &lt;code&gt;chat#index&lt;/code&gt; como root.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/routes.rb&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="s1"&gt;'chat#index'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abra o arquivo &lt;code&gt;app/views/chat/index.html.erb&lt;/code&gt; e coloque o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/chat/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;enviar&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"chat"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos colocar o Action Cable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando o Action Cable
&lt;/h2&gt;

&lt;p&gt;Como a nossa aplicação é um chat, então vamos criar um channel Chat.&lt;/p&gt;

&lt;p&gt;Para criar, basta usar o generator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g channel Chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tem um arquivo que fica no &lt;code&gt;app/channels/application_cable/connection.rb&lt;/code&gt; que fica responsável pela conexão.&lt;/p&gt;

&lt;p&gt;Porém, você tem fazer a parte de autenticação e autorização, mas como a minha aplicação não tem autenticação, então eu vou ignorar essa parte.&lt;/p&gt;

&lt;p&gt;Mas eu vou deixar um exemplo do código de como seria se tivesse uma autenticação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/channels/application_cable/connection.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ApplicationCable&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionCable&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
    &lt;span class="n"&gt;identified_by&lt;/span&gt; &lt;span class="ss"&gt;:current_user&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;
      &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_verified_user&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="kp"&gt;private&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_verified_user&lt;/span&gt;
        &lt;span class="c1"&gt;# se você estiver usando cookie para autenticação&lt;/span&gt;
        &lt;span class="n"&gt;verified_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&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;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="c1"&gt;# se você estiver usando session para autenticação&lt;/span&gt;
        &lt;span class="n"&gt;verified_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&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;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'_session'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="c1"&gt;# se por acaso, você estiver usando uma gem para autenticação, terá pesquisar sobre isso.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;verified_user&lt;/span&gt;
          &lt;span class="n"&gt;verified_user&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;reject_unauthorized_connection&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&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;Você pode observar o &lt;code&gt;identified_by&lt;/code&gt;, ele cria um identificador de conexão, ou seja, você pode usar &lt;code&gt;current_user&lt;/code&gt; para saber quem é o usuário que está conectado em uma conexão.&lt;/p&gt;

&lt;p&gt;Agora, vamos focar no client-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client Side
&lt;/h2&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;app/javascript/channels/chat_channel.js&lt;/code&gt; e coloque o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/channels/chat_channel.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;consumer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;channels/consumer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// o consumer vai ser criado aqui e vai tentar assinar no canal ChatChannel&lt;/span&gt;
&lt;span class="nx"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ChatChannel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// vai executar essa método se a conexão foi sucedida&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enviar_mensagem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="nx"&gt;received&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dados&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Aqui recebe os dados do server side&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dados&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mensagem&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="nx"&gt;enviar_mensagem&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Aqui vai enviar os dados para server side&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dados&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;mensagem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mensagem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dados&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// isso vai enviar os dados para action mensagem do server side&lt;/span&gt;

    &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Server side
&lt;/h2&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;app/channels/chat_channel.rb&lt;/code&gt; e coloque o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/channels/chat_channel.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChatChannel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationCable&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Channel&lt;/span&gt;
  &lt;span class="c1"&gt;# vai executar esse método se o usuário vai fazer uma conexão&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subscribed&lt;/span&gt;
    &lt;span class="c1"&gt;# o stream_from vai assina em um broadcasting com nome 'chat', isso é útil para criar grupo. &lt;/span&gt;
    &lt;span class="n"&gt;stream_from&lt;/span&gt; &lt;span class="s2"&gt;"chat"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# aqui é a action que recebe os dados do client side&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mensagem&lt;/span&gt; &lt;span class="n"&gt;dados&lt;/span&gt;
    &lt;span class="c1"&gt;# isso vai envia a dados para os subscribers (assinantes). O primeiro argumento é o nome do broadcasting, como você pode ver que é igual ao argumento do `stream_from`.&lt;/span&gt;
    &lt;span class="no"&gt;ActionCable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"chat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dados&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, execute o &lt;code&gt;rails server&lt;/code&gt; e abre duas abas do navegador com a url &lt;code&gt;localhost:3000&lt;/code&gt;, tente manda uma mensagem e verá que a outra aba vai receber a mensagem.&lt;/p&gt;

&lt;p&gt;Com isso, nós terminamos por aqui, porém eu vou fazer, um dia, um post, em que vou aprofundar mais o action cable criando um joguinho simples.&lt;/p&gt;

&lt;p&gt;Então é isso, tchau!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>actioncable</category>
    </item>
    <item>
      <title>Usando Action Text em Rails 7</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Fri, 16 Dec 2022 15:33:03 +0000</pubDate>
      <link>https://dev.to/xandekk/usando-action-text-em-rails-7-370b</link>
      <guid>https://dev.to/xandekk/usando-action-text-em-rails-7-370b</guid>
      <description>&lt;p&gt;Hoje, nós vamos aprender a integrar um editor WYSIWYG com rapidez e facilidade na nossa aplicação Rails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observação&lt;/strong&gt;: Será necessário instalar alguns software de terceiro para processamento de imagem.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/libvips/libvips"&gt;libvips&lt;/a&gt; v8.6+ e/ou &lt;a href="https://imagemagick.org/index.php"&gt;ImageMagick&lt;/a&gt; para analise e transformação de imagem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O que é Action Text?
&lt;/h2&gt;

&lt;p&gt;Action Text nos dá a capacidade de criar conteúdo de rich text. Ele usa o editor &lt;a href="https://trix-editor.org/"&gt;Trix&lt;/a&gt; para lidar com tudo, desde a formatação a links, citações, listas, imagens incorporadas. O conteúdo rich text gerado pelo editor Trix é salvo em seu próprio model &lt;code&gt;RichText&lt;/code&gt; associado a qualquer model Active Record existente no aplicativo. E também, quaisquer anexos incorporadas são armazenadas automaticamente usando o Active Storage e associadas ao model &lt;code&gt;RichText&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Bem, chega de papo e vamos construir nossa aplicação.&lt;/p&gt;

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

&lt;p&gt;A aplicação que vou criar é um simples blog.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Agora, vamos instalar o Action Text&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando o Action Text
&lt;/h2&gt;

&lt;p&gt;Para instalar, é bem simples, basta executar o comando abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails action_text:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, com isso, o Action Text está instalado.&lt;/p&gt;

&lt;p&gt;Vamos criar o model e controller.&lt;/p&gt;

&lt;p&gt;Eu vou usar o scaffold, para nos livrar do trabalho.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g scaffold Publicacao titulo conteudo:rich_text
railos db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que eu criei o &lt;code&gt;conteudo&lt;/code&gt; do tipo &lt;code&gt;rich_text&lt;/code&gt;, com isso, o action text está associado com o model &lt;code&gt;Publicacao&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Beleza, mas se eu tiver um model criado, o que eu faço?&lt;/p&gt;

&lt;p&gt;É bem simples, basta colocar o código &lt;code&gt;has_rich_text :nome_do_atributo&lt;/code&gt; no seu model.&lt;/p&gt;

&lt;p&gt;Por exemplo, vamos abrir o arquivo &lt;code&gt;app/models/publicacao.rb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Publicacao&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_rich_text&lt;/span&gt; &lt;span class="ss"&gt;:conteudo&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que o generator colocou para gente, não tem muito segredo em fazer isso.&lt;/p&gt;

&lt;p&gt;Antes de rodar o servidor, vamos observar o arquivo view, para saber como que colocar o editor no form.&lt;/p&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;app/views/publicacaos/_form.html.erb&lt;/code&gt; e foque em uma parte do código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;...
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:conteudo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s2"&gt;"display: block"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rich_text_area&lt;/span&gt; &lt;span class="ss"&gt;:conteudo&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Então, para usar o editor Trix, basta colocar o &lt;code&gt;rich_text_area :nome_do_atributo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Então, vamos ver essa coisa funcionando, rode o servidor e vá para &lt;code&gt;localhost:3000/publicacaos/new&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E verá um editor WYSIWYG, então divirta-se brincando com ele, coloque imagem, use a formatação, etc.&lt;/p&gt;

&lt;p&gt;Bem, nós acabamos por aqui.&lt;/p&gt;

&lt;p&gt;Então é isso, tchau!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>actiontext</category>
    </item>
    <item>
      <title>O básico de Stimulus em Rails</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Thu, 15 Dec 2022 21:53:02 +0000</pubDate>
      <link>https://dev.to/xandekk/o-basico-de-stimulus-em-rails-395j</link>
      <guid>https://dev.to/xandekk/o-basico-de-stimulus-em-rails-395j</guid>
      <description>&lt;p&gt;Talvez você tenha se perguntado a existência da gem &lt;code&gt;stimulus&lt;/code&gt; que Rails instala por padrão, mas não se preocupe, que aqui você vai aprender sobre ele.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observação: Esse post é necessário que tenha um conhecimento DOM. Se não, pode ser complicado em entender.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Stimulus?
&lt;/h2&gt;

&lt;p&gt;Eu vou traduzir a documentação, pois, sinceramente, não consigo explicar isso em outras palavras.&lt;/p&gt;

&lt;p&gt;Stimulus é um framework Javascript com ambições modesta.&lt;br&gt;
Ao contrário de outros frameworks front-end, Stimulus é projetado para aprimorar HTML estático ou renderizado pelo servidor - o "HTML que você possui" - conectando objetos Javascript a elementos da página usando anotações simples.&lt;/p&gt;

&lt;p&gt;Esses objetos JavaScript são chamados de controllers, e o Stimulus monitora continuamente a página esperando que os atributos &lt;code&gt;data-controller&lt;/code&gt; apareçam no HTML. Para cada atributo, o Stimulus examina o valor do atributo para encontrar uma classe controller correspondente, cria uma nova instância dessa classe e a conecta ao elemento.&lt;/p&gt;

&lt;p&gt;Você pode pensar desta maneira: Assim como o atributo &lt;code&gt;class&lt;/code&gt; é uma ponte que conecta HTML a CSS, o atributo &lt;code&gt;data-controller&lt;/code&gt; do Stimulus é uma ponte que conecta HTML a Javascript&lt;/p&gt;

&lt;p&gt;Além dos controllers, os outros três principais conceitos de Stimulus são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;actions&lt;/code&gt;, que conectam métodos do controller a eventos DOM usando atributos &lt;code&gt;data-action&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;targets&lt;/code&gt;, que localizam elementos de significado dentro de um controller;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;values&lt;/code&gt;, que leem, escrevem e observam atributos de dados no elemento do controller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O uso de atributos de dados pelo Stimulus ajuda a separar o conteúdo do comportamento da mesma forma que o CSS separa o conteúdo da apresentação. Além disso, as convenções do Stimulus naturalmente encorajam você a agrupar códigos relacionados por nome.&lt;/p&gt;

&lt;p&gt;Por sua vez, o Stimulus ajuda você a criar controllers pequenos e reutilizáveis, fornecendo estrutura suficiente para evitar que seu código se transforme em uma “sopa de JavaScript”.&lt;/p&gt;

&lt;p&gt;Talvez, com essa explicação, você não tenha entendido muito, então vamos para a prática para fixar isso.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prática
&lt;/h2&gt;

&lt;p&gt;Eu estava pensando que tipo de aplicação eu criaria para isso, porém, não consegui em pensar em nada. Então vai ser uma aplicação aleatória que possa aproveitar o máximo do Stimulus.&lt;/p&gt;

&lt;p&gt;Então, execute os comandos abaixo para preparar o terreno.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new exemplo_stimulus
&lt;span class="nb"&gt;cd &lt;/span&gt;exemplo_stimulus
rails g controller Pagina index
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abra o arquivo &lt;code&gt;config/routes.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/routes.rb&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="s1"&gt;'pagina#index'&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, o nosso terreno está pronto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Controllers
&lt;/h2&gt;

&lt;p&gt;Vá no arquivo &lt;code&gt;app/views/pagina/index.html.erb&lt;/code&gt; e adicione o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/pagina/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rode o servidor e vá para URL &lt;code&gt;localhost:3000&lt;/code&gt; e veja a mágica acontecer.&lt;/p&gt;

&lt;p&gt;Viu, apareceu o "Hello world!", mas como?&lt;/p&gt;

&lt;p&gt;Antes de explicar, o que aconteceu, vamos, primeiro, entender sobre o atributo &lt;code&gt;data-controller&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Como foi explicado lá em cima, que o Stimulus procura no html pelo o atributo &lt;code&gt;data-controller&lt;/code&gt; para criar uma instância de classe e conectar com o elemento.&lt;/p&gt;

&lt;p&gt;Só que a dúvida é, onde está essa classe?&lt;/p&gt;

&lt;p&gt;Bem, na sua aplicação, procure o arquivo no diretório &lt;code&gt;app/javascript/controllers&lt;/code&gt; e verá ele lá.&lt;/p&gt;

&lt;p&gt;Achou? E qual é o nome do arquivo?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hello_controller.js&lt;/code&gt; é o nome do arquivo, ou seja, o Stimulus vai usar o valor do atributo para procurar um arquivo do diretório &lt;code&gt;app/javascript/controllers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos fazer um teste, mude o valor do &lt;code&gt;data-controller&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/pagina/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"ola"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, reinicie a página e verá ...&lt;/p&gt;

&lt;p&gt;Nada, obviamente, esperava o que?&lt;/p&gt;

&lt;p&gt;Bem, por que não apereceu nada?&lt;/p&gt;

&lt;p&gt;É que Stimulus está procurando um arquivo com nome &lt;code&gt;ola_controller.js&lt;/code&gt; e esse arquivo não existe.&lt;/p&gt;

&lt;p&gt;Então, vamos mudar o nome do arquivo &lt;code&gt;hello_controller.js&lt;/code&gt; para &lt;code&gt;ola_controller.js&lt;/code&gt; e reinicie a página.&lt;/p&gt;

&lt;p&gt;Agora, funcionou.&lt;/p&gt;

&lt;p&gt;Uma observação, é necessário que tenha o nome &lt;code&gt;_controller.js&lt;/code&gt; no final do arquivo.&lt;/p&gt;

&lt;p&gt;Bem, eu acho que você sacou como que funciona o &lt;code&gt;data-controller&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora, vamos abrir o &lt;code&gt;app/javascript/controllers/ola_controller&lt;/code&gt; e observar ele.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/controllers/ola_controller&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não tem muito segredo nesse arquivo, então eu vou só explicar o método &lt;code&gt;connect&lt;/code&gt;, pois o resto dá para entender de boa.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;connect&lt;/code&gt; é executado, quando usar o atributo &lt;code&gt;data-controller&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Beleza, agora vamos nos aprofundar um pouco.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actions
&lt;/h2&gt;

&lt;p&gt;Vá para o arquivo &lt;code&gt;app/views/pagina/index.html.erb&lt;/code&gt; e coloque o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/pagina/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"ola"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"keyup-&amp;gt;ola#mudarTexto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, nós temos um novo atributo.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;data-action&lt;/code&gt; serve para lida com evento DOM do seu controller.&lt;/p&gt;

&lt;p&gt;Vamos observar o valor do nosso atributo &lt;code&gt;data-action&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Observando ele, você pode notar um padrão, que é, começa com evento DOM &lt;code&gt;keyup&lt;/code&gt; e vai para o controller &lt;code&gt;ola&lt;/code&gt; e execute o método &lt;code&gt;mudarTexto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ou seja, é desse jeito o padrão &lt;code&gt;evento-&amp;gt;controller#método&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Não tem muito mistério sobre isso, basta lembrar desse padrão.&lt;/p&gt;

&lt;p&gt;Então vamos para o arquivo &lt;code&gt;app/javascript/controllers/ola_controller.js&lt;/code&gt; e colocar o novo método e remover o &lt;code&gt;connect&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/controllers/ola_controller.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mudarTexto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, reinicie a página e abra o dev tools para ver o console.&lt;/p&gt;

&lt;p&gt;Viu, ele está imprimindo o valor do input.&lt;/p&gt;

&lt;p&gt;Você pode pensar, nossa, que simples.&lt;/p&gt;

&lt;p&gt;Sim, de fato, é muito simples.&lt;/p&gt;

&lt;p&gt;Agora vamos mergulhar mais, que já estamos quase no fim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Targets
&lt;/h2&gt;

&lt;p&gt;Novamente, edite o arquivo, &lt;code&gt;app/views/pagina/index.html.erb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/pagina/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"ola"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"keyup-&amp;gt;ola#mudarTexto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-ola-target=&lt;/span&gt;&lt;span class="s"&gt;"texto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hum, um outro atributo.&lt;/p&gt;

&lt;p&gt;Esse atributo é bem diferente, se prestar atenção, você pode ver o nome do controller no meio, ou seja, para usar ele, tem que seguir esse padrão, &lt;code&gt;data-nome_do_controller-target&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mas a questão é, o que ele faz?&lt;/p&gt;

&lt;p&gt;Como o nome diz, ele é um alvo do controller. &lt;/p&gt;

&lt;p&gt;O uso dele seria equivalente a &lt;code&gt;GetElementById&lt;/code&gt;, só que mais simples.&lt;/p&gt;

&lt;p&gt;Vamos para o arquivo &lt;code&gt;app/javascript/controllers/ola_controller.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/controllers/ola_controller.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;texto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;mudarTexto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textoTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`olá, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pode notar que existe uma variável &lt;code&gt;targets&lt;/code&gt;, em que, está atribuindo um array com um valor &lt;code&gt;"texto"&lt;/code&gt;, ou seja, tem ter o valor igual, onde foi posto no HTML.&lt;/p&gt;

&lt;p&gt;Agora, se você observar o &lt;code&gt;this.textoTarget&lt;/code&gt;, ele é o elemento, a qual você colocou o atributo &lt;code&gt;data-ola-target&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Então reinicie a página, e veja a mágica acontecer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Values
&lt;/h2&gt;

&lt;p&gt;O último conceito do Stimulus, então, abra o arquivo index novamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/pagina/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"ola"&lt;/span&gt; &lt;span class="na"&gt;data-ola-nome-value=&lt;/span&gt;&lt;span class="s"&gt;"Zulano"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"keyup-&amp;gt;ola#mudarTexto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-ola-target=&lt;/span&gt;&lt;span class="s"&gt;"texto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beleza, antes de explicar esse atributo, vamos primeiro para o arquivo javascript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/controllers/ola_controller.js.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;texto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;mudarTexto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nomeValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textoTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`olá, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pode notar que ele meio que equivalente ao target, o que muda é que o targets aceita um array, enquanto o values é um JSON.&lt;/p&gt;

&lt;p&gt;O padrão do atributo é &lt;code&gt;data-nome_do_controller-chave-value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Novamente, reinicie a página e veja o console do dev tools.&lt;/p&gt;

&lt;p&gt;Bem, eu vou acabar por aqui, isso é o básico do Stimulus.&lt;/p&gt;

&lt;p&gt;Eu sinto que esse post foi um desastre, mas se houver qualquer dúvida, pode comentar que vou responder.&lt;/p&gt;

&lt;p&gt;Bem, então é isso, tchau!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>stimulus</category>
    </item>
    <item>
      <title>Uma introdução de Active Storage em Rails 7</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Wed, 14 Dec 2022 21:04:46 +0000</pubDate>
      <link>https://dev.to/xandekk/uma-introducao-de-active-storage-em-rails-7-13f1</link>
      <guid>https://dev.to/xandekk/uma-introducao-de-active-storage-em-rails-7-13f1</guid>
      <description>&lt;p&gt;Se você quer que sua aplicação Rails seja capaz de lidar arquivos, como imagens, videos, pdfs, etc. Você está no lugar certo.&lt;/p&gt;

&lt;p&gt;Hoje, nós vamos aprender sobre Active Storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Active Storage
&lt;/h2&gt;

&lt;p&gt;Active Storage é uma ferramenta que facilita o upload de arquivos para serviço de armazenamento em nuvem como Amazon S3, Google Cloud Storage ou Microsoft Azure e anexa esses arquivos a objetos Active Record. Ele também vem com um serviço baseado em disco local para desenvolvimento e teste e suporta espelhamento de arquivos para serviços subordinados para backups e migrações.&lt;/p&gt;

&lt;p&gt;Observação: Eu não vou mostrar como que integrar o Active Storage com o serviço de armazenamento em nuvem. Eu só vou focar em ambiente de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Mas, antes de instalar Active Storage na sua aplicação, é necessário alguns software de terceiro para ter suporte em analise e processamento de arquivos.&lt;/p&gt;

&lt;p&gt;Eu vou deixar uma lista de software.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/libvips/libvips" rel="noopener noreferrer"&gt;libvips&lt;/a&gt; v8.6+ ou &lt;a href="https://imagemagick.org/index.php" rel="noopener noreferrer"&gt;ImageMagick&lt;/a&gt; para analise e transformação de imagem.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ffmpeg.org/" rel="noopener noreferrer"&gt;ffmpeg&lt;/a&gt; v3.4+ para pré-visualizações de vídeo e ffprobe para analise de video/audio&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://poppler.freedesktop.org/" rel="noopener noreferrer"&gt;poppler&lt;/a&gt; ou &lt;a href="https://mupdf.com/" rel="noopener noreferrer"&gt;muPDF&lt;/a&gt; para pré-visualizações de PDF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E também é necessário colocar uma gem &lt;code&gt;image_processing&lt;/code&gt;, se sua aplicação vai usar arquivo do tipo imagem.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Antes de instalar e usar software de terceiros, certifique-se de compreender as implicações de licenciamento de fazê-lo. O MuPDF, em particular, é licenciado sob AGPL e requer uma licença comercial para alguns usos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eu vou ensinar a instalar o Active Storage criando uma aplicação, porque eu acho muito mais melhor você ver a construção da aplicativo.&lt;/p&gt;

&lt;p&gt;Então vamos criar aplicação&lt;/p&gt;

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

&lt;p&gt;A aplicação que eu vou criar vai ser um simples armazenamento de arquivos, em que vai ter dois models e controllers, &lt;code&gt;Usuario&lt;/code&gt; e &lt;code&gt;Arquivo&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;rails new armazenamento
&lt;span class="nb"&gt;cd &lt;/span&gt;armazenamento
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos colocar uma gem no &lt;code&gt;Gemfile&lt;/code&gt; para que possa ter suporte de imagem.&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"gem 'image_processing'"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; Gemfile
bundle &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com gem instalado, vamos instalar o Active Storage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails active_storage:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comando cria uma migração, em que tem três tabelas &lt;code&gt;active_storage_blobs&lt;/code&gt;, &lt;code&gt;active_storage_attachments&lt;/code&gt; e &lt;code&gt;active_storage_variant_records&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Eu não vou explicar cada um dele, mas saiba que são essas tabelas que vai armazenar os arquivos.&lt;/p&gt;

&lt;p&gt;Como ele gerou uma migração, vamos migrar ele.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos criar os models e os controllers.&lt;/p&gt;

&lt;p&gt;Antes de criar um model, tenho que falar que existe duas maneiras de anexar o arquivo no model, uma é usando o generator e outro é colocando o código na mão, o que não é complicado de fazer.&lt;/p&gt;

&lt;p&gt;Primeiro, vamos usar o generator no model &lt;code&gt;Usuario&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;rails g model Usuario email senha avatar:attachment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como você pode ver o tipo &lt;code&gt;attachment&lt;/code&gt;, ele indica que esse model vai ter um anexo, ou seja, vai ter somente um arquivo, se você quer que seja vários arquivos, basta usar o tipo &lt;code&gt;attachments&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Beleza, vamos ver o que ele gerou para nós, vá para o arquivo &lt;code&gt;app/models/usuario.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/usuario.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Usuario&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_one_attached&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;has_one_attached&lt;/code&gt; é uma macro que configura uma relação um para um entre o registro e o arquivo, ou seja, cada registro só pode ter um arquivo.&lt;/p&gt;

&lt;p&gt;Isso é perfeito para gente, pois nós queremos que seja uma imagem do usuário.&lt;/p&gt;

&lt;p&gt;E o que generator gerou foi isso, ou seja, se eu não quiser usar o generator, basta colocar esse código no model e pronto.&lt;/p&gt;

&lt;p&gt;Então, vamos criar um model sem usar o tipo &lt;code&gt;attachment&lt;/code&gt; ou &lt;code&gt;attachments&lt;/code&gt; e colocar o código na mão.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g model Arquivo 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora abra no arquivo &lt;code&gt;app/models/arquivo.rb&lt;/code&gt; para colocar o código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/arquivo.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Arquivo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many_attached&lt;/span&gt; &lt;span class="ss"&gt;:arquivos&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode ter percebido que eu escrevi diferente do código de cima.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;has_many_attached&lt;/code&gt; é uma macro que configura uma relação de um para muitos entre o registro e os arquivos, ou seja, cada registro pode ter mais de um arquivo.&lt;/p&gt;

&lt;p&gt;Viu, é simples implementar sem o generator.&lt;/p&gt;

&lt;p&gt;Agora que criamos os models, vamos migrar eles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com models criado e migrado, vamos criar os controllers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g controller Usuarios index show new edit
rails g controller Arquivos index show new edit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos editar esses controllers. vamos primeiro para &lt;code&gt;app/cotrollers/usuarios_controller.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/cotrollers/usuarios_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsuariosController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:define_usuario&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@usuarios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="vi"&gt;@usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usuario_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;usuario_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;edit&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arquivo_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;usuario_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;usuarios_path&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt; 

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;usuario_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:usuario&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&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;:senha&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;define_usuario&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="vi"&gt;@usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordNotFound&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;usuarios_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :not_found&lt;/span&gt;
    &lt;span class="k"&gt;end&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;Como você viu o código que eu escrevi, não tem nada demais, ou seja, a imagem vai ser salva, se o usuário colocar uma imagem no form.&lt;/p&gt;

&lt;p&gt;Só que a história muda um pouquinho, quando nós estamos lidando em que aceita vários arquivos.&lt;/p&gt;

&lt;p&gt;Então abra o arquivo &lt;code&gt;app/controllers/arquivos_controller.rb&lt;/code&gt; e coloque o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/arquivos_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArquivosController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:define_arquivo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@arquivos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="vi"&gt;@arquivo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@arquivo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arquivo_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;arquivo_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;edit&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arquivo_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;arquivo_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;arquivos_path&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt; 

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;arquivo_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:arquivo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;arquivos: &lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;define_arquivo&lt;/span&gt;
    &lt;span class="vi"&gt;@arquivo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&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;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;arquivos_attachments: :blob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@arquivo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;arquivos_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :not_found&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&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;Se você observar o código, talvez você vai ver algo que nunca tenha visto antes, percebeu?&lt;/p&gt;

&lt;p&gt;Se não percebeu, observe no método &lt;code&gt;arquivo_params&lt;/code&gt; e me diz o que tem diferente do controller &lt;code&gt;Usuario&lt;/code&gt; e &lt;code&gt;Arquivo&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;No controller usuario, o avatar está igual aos outros atributos, enquanto no controller arquivo, ele está com um array.&lt;/p&gt;

&lt;p&gt;Então, lembre-se de que se você estiver lidando com muitos arquivos, coloque o array, se não, use um &lt;code&gt;symbol&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E também outra diferença, no método &lt;code&gt;define_arquivo&lt;/code&gt;, eu utilizei o &lt;code&gt;where&lt;/code&gt; e o &lt;code&gt;includes&lt;/code&gt;. O motivo de fazer isso foi para evitar o problema de n+1, se não sabe sobre esse problema, eu recomendo que pesquise sobre isso.&lt;/p&gt;

&lt;p&gt;Agora, com controllers criado, vamos editar as rotas, abra o arquivo &lt;code&gt;config/routes.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/routes.rb&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:arquivos&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:usuarios&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com models, controllers e rotas editado, agora faltam os views.&lt;/p&gt;

&lt;p&gt;Primeiro, vamos editar views de usuarios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/usuarios/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="vi"&gt;@usuarios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;usuario&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="n"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usuarios_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_usuario_path&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/usuarios/new.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_with&lt;/span&gt; &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="n"&gt;usuarios_path&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_field&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:senha&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password_field&lt;/span&gt; &lt;span class="ss"&gt;:senha&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;file_field&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para que possa enviar um arquivo a partir de um &lt;code&gt;form&lt;/code&gt;, você pode usar o &lt;code&gt;file_field&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/usuarios/show.html.erb --&amp;gt;&lt;/span&gt;
avatar: &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;image_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
email: &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para poder exibir uma imagem, você pode usar o &lt;code&gt;image_tag&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora rode o servidor e vai para url &lt;code&gt;localhost:3000/usuarios&lt;/code&gt; e crie um usuario com imagem e veja a coisa funciona.&lt;/p&gt;

&lt;p&gt;Agora, vamos editar os views de arquivos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/arquivos/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="vi"&gt;@arquivos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arquivo_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_arquivo_path&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/arquivos/new.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_with&lt;/span&gt; &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="n"&gt;arquivos_path&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:arquivos&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;file_field&lt;/span&gt; &lt;span class="ss"&gt;:arquivos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;multiple: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pode perceber que &lt;code&gt;file_field&lt;/code&gt; é diferente do usuario, o &lt;code&gt;multiple: true&lt;/code&gt; indica que esse campo aceita vários arquivos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/arquivos/show.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="vi"&gt;@arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arquivos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_with?&lt;/span&gt; &lt;span class="s2"&gt;"image"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;image_tag&lt;/span&gt; &lt;span class="n"&gt;arquivo&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_with?&lt;/span&gt; &lt;span class="s2"&gt;"video"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;video_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;controls: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- o video_tag recebe o primeiro argumento uma url do arquivo e esse controls é para ativar o controle do video --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Se não for uma imagem e nem video, baixe ele --&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rails_blob_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;disposition: &lt;/span&gt;&lt;span class="s2"&gt;"attachment"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- o arquivo.filename mostra o nome do arquivo --&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- o rails_blob_path cria um link de download --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vá para url &lt;code&gt;localhost:3000/arquivos&lt;/code&gt; e adicione vários arquivos de tipo diferente.&lt;/p&gt;

&lt;p&gt;Você pode notar, se você colocou um arquivo que não seja imagem e video, ao clicar no arquivo, ele vai fazer download.&lt;/p&gt;

&lt;p&gt;E nós acabamos por aqui.&lt;/p&gt;

&lt;p&gt;Então, espero que tenha ajudado e tchau!&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Como usar o Active Job em Rails 7</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Tue, 13 Dec 2022 15:54:18 +0000</pubDate>
      <link>https://dev.to/xandekk/como-usar-o-active-job-em-rails-7-2f0g</link>
      <guid>https://dev.to/xandekk/como-usar-o-active-job-em-rails-7-2f0g</guid>
      <description>&lt;p&gt;Quando você está desenvolvendo uma aplicação, em que o usuário pode se cadastrar, e quando se faz o cadastro, o usuário recebe um email da aplicação.&lt;/p&gt;

&lt;p&gt;Só que a minha pergunta é?&lt;/p&gt;

&lt;p&gt;Você faria a aplicação enviar o email imediatamente? &lt;/p&gt;

&lt;p&gt;E se, por acaso, a aplicação demorar mais do que esperado para enviar o email? Isso pode ser uma experiência nada agradável para usuário, pois ele fez o cadastro e ainda está no loading, sendo que deveria está na página principal.&lt;/p&gt;

&lt;p&gt;Então, para resolver isso, basta que o email seja enviado em background (segundo plano). Ao fazer isso, ele vai ser enqueued (enfileirado) para ser enviado depois, e dessa forma, quando o usuário se cadastrar, ele vai ser imediatamente redirecionado para página principal, ao invés, de ficar esperando.&lt;/p&gt;

&lt;p&gt;Beleza, então como que faz isso?&lt;/p&gt;

&lt;p&gt;Bem, antes de fazer isso, primeiro, vamos saber o que é Active Job.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Active Job
&lt;/h2&gt;

&lt;p&gt;Active Job é um framework para declarar jobs (tarefas) e executá-las em uma variedade de queuing back-ends (back-ends de enfileiramento).&lt;/p&gt;

&lt;p&gt;Esses jobs (tarefas) podem ser o exemplo que citei em cima de enviar o email, mas também como, fazer cobrança de um produto, ou então executar um código que pode levar um tempo, como usar um API de terceiro.&lt;/p&gt;

&lt;p&gt;Agora vamos entender a proposta do Active Job.&lt;/p&gt;

&lt;h2&gt;
  
  
  A proposta do Active Job
&lt;/h2&gt;

&lt;p&gt;Eu vou traduzir o que tem na documentação oficial.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O ponto principal é garantir que todos os aplicativos Rails tenham uma infraestrutura de job (tarefa) instalada. Podemos então ter recursos de estrutura e outras gems construídas sobre isso, sem ter que nos preocupar com as diferenças de API entre vários executores de jobs (tarefas), como Delayed Job e Resque. Então escolher seu back-end de filas torna-se mais uma preocupação operacional. E você poderá alternar entre eles sem precisar reescrever seus jobs.&lt;/p&gt;

&lt;p&gt;Por padrão, o Rails vem com uma implementação de enfileiramento assíncrono que executa jobs (tarefas) com um pool de encadeamentos em processo. Os trabalhos serão executados de forma assíncrona, mas todos os trabalhos na fila serão descartados na reinicialização.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ou seja, simplificando a explicação, ele tira a necessidade de ficar mudando o código, caso você queira usar uma gem diferente de executadores de jobs (tarefas).&lt;/p&gt;

&lt;p&gt;Por exemplo, você está usando o Delayed Job, porém ele não tem o que você quer e então troca para Resque e isso sem ter que se preocupar de mudar o código.&lt;/p&gt;

&lt;p&gt;É claro que vai haver algumas coisas para configurar, mas isso é irrelevante.&lt;/p&gt;

&lt;p&gt;Beleza, agora que nós sabemos sobre Active Job e a proposta dele, vamos pôr a mão na massa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando um job
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g job Tarefa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abra o arquivo &lt;code&gt;app/jobs/tarefa_job.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;
  &lt;span class="c1"&gt;# faça alguma coisa aqui&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beleza, não tem muita coisa que falar sobre esse código, somente o &lt;code&gt;queue_as&lt;/code&gt; e &lt;code&gt;perform&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos falar sobre &lt;code&gt;queue_as&lt;/code&gt;. Esse método serve para indicar qual fila usar para esse job, isso é útil, para caso em que você tem vários jobs diferentes e não quer executar todos eles em uma única fila e sim em filas diferentes.&lt;/p&gt;

&lt;p&gt;Agora sobre o &lt;code&gt;perform&lt;/code&gt;, eu não sei como explicar ele.&lt;/p&gt;

&lt;p&gt;Só saiba que é nesse método que você coloca o código para ser executado usando o &lt;code&gt;perform_now&lt;/code&gt; ou &lt;code&gt;perform_later&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E uma coisa, não modifique o nome do método, se não vai funcionar o código, mas você pode tirar ou adicionar mais argumentos.&lt;/p&gt;

&lt;p&gt;Pronto, Com a explicação dada, vamos enfileirar o job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enfileirando o job
&lt;/h2&gt;

&lt;p&gt;Para enfileirar o job que nós criamos, basta usar o perform_later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;TarefaJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt; &lt;span class="s2"&gt;"Alexandre"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O método &lt;code&gt;perform_later&lt;/code&gt; enfileirar o job na fila e vai executar o job, somente se a fila estiver livre.&lt;/p&gt;

&lt;p&gt;Você pode definir que hora ou dias ele vai ser executado, usando o &lt;code&gt;set&lt;/code&gt;, veja um exemplo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;TarefaJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;wait: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;week&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt; &lt;span class="s2"&gt;"Alexandre"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O job vai ser enfileirado para ser executado daqui uma semana.&lt;/p&gt;

&lt;p&gt;E é isso. Nós terminamos por aqui.&lt;/p&gt;

&lt;p&gt;Eu sei que está faltando sobre os back-ends, como Sidekiq, Resque, Delayed Job, e outros.&lt;/p&gt;

&lt;p&gt;Mas como eu disse lá em cima na proposta de Active Job, não vai ser necessário mudar o código, só basta configurar a gem que você vai ser capaz de usar ele.&lt;/p&gt;

&lt;p&gt;Eu vou fazer um post no futuro, testando cada um dele, se for possível.&lt;/p&gt;

&lt;p&gt;Então é isso, Tchau!&lt;/p&gt;

</description>
      <category>welcome</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Uma introdução sobre Action Mailer em Rails 7</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Mon, 12 Dec 2022 13:11:27 +0000</pubDate>
      <link>https://dev.to/xandekk/uma-introducao-sobre-action-mailer-em-rails-7-jn3</link>
      <guid>https://dev.to/xandekk/uma-introducao-sobre-action-mailer-em-rails-7-jn3</guid>
      <description>&lt;p&gt;Nessa introdução, eu vou ensinar a usar action mailer.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Action Mailer?
&lt;/h2&gt;

&lt;p&gt;O Action Mailer é um recurso de Rails que permite enviar email da sua aplicação.&lt;/p&gt;

&lt;p&gt;Uma característica bem interessante do Action Mailer é que ele é bem similar ao Controller, ou seja, tudo que você aprendeu sobre Controller, pode ser aplicado em Mailer.&lt;/p&gt;

&lt;p&gt;Vamos ver quais são as semelhanças entre Controller e Mailer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Actions e views.&lt;/li&gt;
&lt;li&gt;Variáveis ​​de instância que é acessível no views.&lt;/li&gt;
&lt;li&gt;A capacidade de usar layouts e partials.&lt;/li&gt;
&lt;li&gt;A capacidade de acessar um hash de parâmetros.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora que você sabe o que é Mailer, vamos pôr em prática.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pondo em prática
&lt;/h2&gt;

&lt;p&gt;Vamos criar uma aplicação simples de autenticação de usuário.&lt;/p&gt;

&lt;p&gt;Se quiser acompanhar, basta executar os comandos abaixo.&lt;/p&gt;

&lt;p&gt;Primeiro, vamos criar um projeto.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Com projeto criado, vamos usar o scaffold para criar o model e controller de uma vez.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g scaffold Usuario nome email senha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, nós temos um projeto para ação.&lt;/p&gt;

&lt;p&gt;Como nós podemos criar o mailer?&lt;/p&gt;

&lt;p&gt;Bem, o jeito mais rápido seria usar o generator.&lt;/p&gt;

&lt;p&gt;Então vamos usar o generator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando mailer
&lt;/h2&gt;

&lt;p&gt;Eu quero que a aplicação envie um email de saudação para o usuário que cadastrou na aplicação.&lt;/p&gt;

&lt;p&gt;Então vamos criar o mailer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g mailer Usuario bem_vindo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O mailer foi criado com nome &lt;code&gt;Usuario&lt;/code&gt; e o &lt;code&gt;bem_vindo&lt;/code&gt; é a action dele.&lt;/p&gt;

&lt;p&gt;Vamos ver o arquivo &lt;code&gt;app/mailers/usuario_mailer.rb&lt;/code&gt; para ver o que o generator gerou.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/mailers/usuario_mailer.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsuarioMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bem_vindo&lt;/span&gt;
    &lt;span class="vi"&gt;@greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hi"&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"to@example.org"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O método &lt;code&gt;bem_vindo&lt;/code&gt; que é a action que nós colocamos no generator e você pode notar que ele também criou um view para essa action, veja no &lt;code&gt;app/views/usuario_mailer/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;mail&lt;/code&gt; cria uma mensagem de email atual. O &lt;code&gt;to: "to@example.org"&lt;/code&gt; é o email para quem a aplicação vai enviar.&lt;/p&gt;

&lt;p&gt;Agora vamos tirar o código gerado do método e colocar o que queremos para que possa enviar o email.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/mailers/usuario_mailer.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsuarioMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bem_vindo&lt;/span&gt;
    &lt;span class="vi"&gt;@usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:usuario&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;subject: &lt;/span&gt;&lt;span class="s1"&gt;'Bem vindo ao meu site'&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;Podemos percebe que no método &lt;code&gt;mail&lt;/code&gt;, existe outra argumento além do &lt;code&gt;to&lt;/code&gt;. O &lt;code&gt;subject&lt;/code&gt; é o assunto do email.&lt;/p&gt;

&lt;p&gt;Agora, Vamos editar a view, pois nós queremos fazer uma mensagem de saudação.&lt;/p&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;app/views/usuario_mailer/bem_vindo.html.erb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- app/views/usuario_mailer/bem_vindo.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nome&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;, bem vindo ao meu site.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Espero que goste do conteúdo do site.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos editar o controller, para que envie o email ao criar o usuário.&lt;/p&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;app/controllers/usuarios_controller.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/usuarios_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsuariosController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usuario_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
        &lt;span class="no"&gt;UsuarioMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;usuario: &lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;bem_vindo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deliver_later&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;usuario_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;notice: &lt;/span&gt;&lt;span class="s2"&gt;"Usuario was successfully created."&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;location: &lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="vi"&gt;@usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&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;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&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;Vamos focar nesse comando &lt;code&gt;UsuarioMailer.with(usuario: @usuario).bem_vindo.deliver_later&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;UsuarioMailer&lt;/code&gt; é classe que nós criamos.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;with&lt;/code&gt; é usado para que você possa passar alguma variável para mailer, no nosso caso, nós estamos passando a variável &lt;code&gt;@usuario&lt;/code&gt; e para acessar no mailer, basta usar o &lt;code&gt;params[:nome_que_voce_passou_no_metodo]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;bem_vindo&lt;/code&gt; está, obviamente, chamando o método que nós criamos.&lt;/p&gt;

&lt;p&gt;E por último, temos o método &lt;code&gt;deliver_later&lt;/code&gt;, o que ele faz é  basicamente enviar o email assincronamente, ou seja, a aplicação não vai ficar esperando a execução de envio de email para poder executar os próximos comandos.&lt;/p&gt;

&lt;p&gt;E se você não queira enviar o email depois, basta usar o &lt;code&gt;deliver_now&lt;/code&gt; que ele vai enviar imediatamente.&lt;/p&gt;

&lt;p&gt;Agora vamos rodar o servidor, para ver em ação.&lt;/p&gt;

&lt;p&gt;Antes de rodar o servidor, migre o banco de dados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails db:migrate
rails server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vá no navegador e acesse no &lt;code&gt;http://127.0.0.1:3000/usuarios&lt;/code&gt; e crie um novo usuário, saiba que agora, a aplicação não vai enviar o email.&lt;/p&gt;

&lt;p&gt;Assim que você criar o usuário, vá no terminal e você vai ver o html do view que nós editamos no &lt;code&gt;app/views/usuario_mailer/bem_vindo.html.erb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Isso significa que até aqui está funcionando.&lt;/p&gt;

&lt;p&gt;Mas nós não queremos que aplicação mostre no terminal, queremos que a aplicação envie para Gmail do usuário.&lt;/p&gt;

&lt;p&gt;Aqui, eu vou usar o Gmail para enviar, se você quer usar outros serviços, vai ter que pesquisar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enviando email usando Gmail
&lt;/h2&gt;

&lt;p&gt;Vá no &lt;code&gt;config/environments/development.rb&lt;/code&gt; e adicione o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"active_support/core_ext/integer/time"&lt;/span&gt;

&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action_mailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delivery_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:smtp&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action_mailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;smtp_settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;address:              &lt;/span&gt;&lt;span class="s1"&gt;'smtp.gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;port:                 &lt;/span&gt;&lt;span class="mi"&gt;587&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;user_name:            &lt;/span&gt;&lt;span class="s1"&gt;'SEU_EMAIL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;password:             &lt;/span&gt;&lt;span class="s1"&gt;'SUA_SENHA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;authentication:       &lt;/span&gt;&lt;span class="s1"&gt;'plain'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;enable_starttls_auto: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;open_timeout:         &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;read_timeout:         &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Em 15 de julho de 2014, o Google aumentou suas &lt;a href="https://support.google.com/accounts/answer/6010255"&gt;medidas de segurança&lt;/a&gt; para bloquear tentativas de aplicativos que considera menos seguros. Você pode alterar suas configurações do Gmail &lt;a href="https://www.google.com/settings/security/lesssecureapps"&gt;aqui&lt;/a&gt; para permitir as tentativas. Se sua conta do Gmail tiver autenticação de 2 fatores habilitada, você precisará definir uma &lt;a href="https://myaccount.google.com/apppasswords"&gt;senha de aplicativo&lt;/a&gt; e usá-la em vez de sua senha normal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Com isso, você vai conseguir enviar o email, então tome cuidado para não enviar para um email de alguém aleatório.&lt;/p&gt;

&lt;p&gt;Então é isso, nós acabamos por aqui, claro que tem muitas coisas que não citei, mas eu decidi que não era relevante assim na introdução, pois com isso, já é capaz de fazer muita coisa.&lt;/p&gt;

&lt;p&gt;E tchau!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>actionmailer</category>
    </item>
    <item>
      <title>Testando routes em RSpec Rails</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Sat, 10 Dec 2022 14:01:17 +0000</pubDate>
      <link>https://dev.to/xandekk/testando-routes-em-rspec-rails-cbj</link>
      <guid>https://dev.to/xandekk/testando-routes-em-rspec-rails-cbj</guid>
      <description>&lt;p&gt;Bem, eu estava pensando que realmente vale a pena fazer esse post, tipo, é algo tão simples, mas tão simples que basta eu mostrar o código que você já entenderia o que está acontecendo.&lt;/p&gt;

&lt;p&gt;Mas um certo alguém falou, "Melhor um código testado, por mais que seja bobo", e concordo com ele, vai que acontece algo imprevisível por esse motivo bobo?&lt;/p&gt;

&lt;p&gt;Mas eu só vou mostrar o código e explicar o que esse código faz e pronto, só isso, porque não tem muito explicar, se você não entendeu, então prova que está faltando conhecimento em rotas em rails.&lt;/p&gt;

&lt;p&gt;Se você quer saber mais de rotas, basta ler a documentação oficial do rails que tem português, aqui está o link, &lt;a href="https://guiarails.com.br/routing.html"&gt;Rotas do Rails de Fora pra Dentro&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bem, aqui está o código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"rails_helper"&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"rotas para Produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:routing&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:produto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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;"colar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"rotas /produtos para action index de controller Produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/produtos"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;
      &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"rotas /produtos/:id para action show de controller Produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/produtos/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;
      &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"show"&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;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"rotas /produtos/new para action new de controller Produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/produtos/new"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;
      &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"rotas /produtos/:id/edit para action edit de controller Produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/produtos/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/edit"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;
      &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"edit"&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;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"rotas /produtos para action create de controller Produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/produtos"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;
      &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"create"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"rotas /produtos para action update de controller Produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/produtos/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;
      &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"update"&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;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"rotas /produtos para action delete de controller Produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/produtos/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;
      &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"produtos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"destroy"&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;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&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;Bem, como que eu explico isso.&lt;/p&gt;

&lt;p&gt;Serio, eu não sei como que explicar algo obvio.&lt;/p&gt;

&lt;p&gt;Eu vou acabar aqui, justamente por isso, então se tiver algumas dúvidas, pode colocar no cometário, que eu vou responder e quem sabe eu coloco a resposta nessa postagem.&lt;/p&gt;

&lt;p&gt;Então é isso, tchau!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>rspec</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testando views em RSpec Rails</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Fri, 09 Dec 2022 14:26:22 +0000</pubDate>
      <link>https://dev.to/xandekk/testando-views-em-rspec-rails-4nh7</link>
      <guid>https://dev.to/xandekk/testando-views-em-rspec-rails-4nh7</guid>
      <description>&lt;p&gt;Até agora, nós testamos o model e request, ainda falta views, system, mailer, channel e routes.&lt;/p&gt;

&lt;p&gt;Também existe outros, como controller, feature, helper, job e mailbox, porém alguns deles estão obsoleta ou é trivial para gente.&lt;/p&gt;

&lt;p&gt;O nosso foco é Views.&lt;/p&gt;

&lt;p&gt;Mas o que é que vamos testar nele?&lt;/p&gt;

&lt;p&gt;Bem, o conteúdo.&lt;/p&gt;

&lt;p&gt;Nós vamos testar se a view está de fato com informação que precisamos.&lt;/p&gt;

&lt;p&gt;Lembre-se que esse teste não testa o javascript.&lt;/p&gt;

&lt;p&gt;Mas talvez você se pergunte de o por quê desse teste.&lt;/p&gt;

&lt;p&gt;Bem, vamos criar um situação aqui, imagine que você tem um e-commerce e então um usuário clica em um produto chamado "Camiseta de Boku no hero" e ele é redirecionado para outra página que tem mais detalhes sobre essa camiseta, porém o usuário descobre que a página está com informação errada, porque produto não é o que ele escolheu, pois o nome do produto está "Camiseta de Boku no pico" e convenhamos que isso é problemático.&lt;/p&gt;

&lt;p&gt;Então, o que aconteceu?&lt;/p&gt;

&lt;p&gt;Depende, existe muitos fatores que pode ter ocorrido para causar esse problema.&lt;/p&gt;

&lt;p&gt;Mas como evitaria esse problema?&lt;/p&gt;

&lt;p&gt;Bem, testando.&lt;/p&gt;

&lt;p&gt;Se tivesse testado que o conteúdo está correto, talvez descobriria a fonte do problema, mas não, você decidiu que esse teste é irrelevante.&lt;/p&gt;

&lt;p&gt;Bem, chega de papo, vamos construir a aplicação.&lt;/p&gt;

&lt;p&gt;A nossa aplicação só vai ter um controller e um model, que é o produto, só isso.&lt;/p&gt;

&lt;p&gt;Se quiser acompanhar a gente, basta executar os comandos abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new teste_views &lt;span class="nt"&gt;--skip-test&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;teste_views
rails db:create db:migrate
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'gem "rspec-rails", group: [:development, :test]'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; Gemfile
bundle &lt;span class="nb"&gt;install
&lt;/span&gt;rails g rspec:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bem, com a aplicação criada, vamos criar o model e o controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g model Produto nome preco:float descricao:text
rails db:migrate
rails g controller Produtos index
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O nosso controller só vai ter uma action, pois, no nosso caso, não será necessário ter os &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;O nosso model tem nome, preço e descrição, e são eles que tem a informação que nós queremos testar.&lt;/p&gt;

&lt;p&gt;Vamos para &lt;code&gt;spec/views/produtos/index.html.erb_spec.rb&lt;/code&gt; e adiciona o teste.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/views/produtos/index.html.erb_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"produtos/index.html.erb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :view&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"Deve mostrar todos os produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;nome: &lt;/span&gt;&lt;span class="s2"&gt;"Camiseta de Boku no hero"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;preco: &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;descricao: &lt;/span&gt;&lt;span class="s2"&gt;"Uma camiseta de Midoriya"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;nome: &lt;/span&gt;&lt;span class="s2"&gt;"Camiseta de One piece"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;preco: &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;descricao: &lt;/span&gt;&lt;span class="s2"&gt;"Uma camiseta de Zoro"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:produtos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;render&lt;/span&gt;

    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s2"&gt;"Camiseta de Boku no hero"&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s2"&gt;"Camiseta de One piece"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"Não deve ter os produtos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:produtos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;render&lt;/span&gt;

    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s2"&gt;"Camiseta de Boku no hero"&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s2"&gt;"Camiseta de One piece"&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;Bem, é pequeno, o teste.&lt;/p&gt;

&lt;p&gt;E de fato, é pequeno, porque não tem muito o que testar além do conteúdo.&lt;/p&gt;

&lt;p&gt;Bem, vamos analisar o código, o que podemos ver de coisas novas, se você acompanha essa série que fiz, são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;assign&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;render&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rendered&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;match&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos de cada vez.&lt;/p&gt;

&lt;p&gt;Eu não sei se você lembra do método &lt;code&gt;assigns&lt;/code&gt; que usamos no teste de request, apesar de ter nome iguais, o que difere é a letra &lt;code&gt;s&lt;/code&gt; no final, e a funcionalidade deles são diferentes.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;assigns&lt;/code&gt; pega o valor da variável de instância do controller, enquanto o &lt;code&gt;assign&lt;/code&gt; atribui para uma variável de instância do controller.&lt;/p&gt;

&lt;p&gt;Agora vamos ver os argumentos que eu passei, no primeiro argumento, eu passei um symbol do nome da variável, isso significa que ele vai atribuir o valor para o &lt;code&gt;@produtos&lt;/code&gt;, e o segundo argumento é o valor e eu coloquei uma array de produtos.&lt;/p&gt;

&lt;p&gt;Não tem muito segredo nesse método, então é isso.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;render&lt;/code&gt; é o método que renderizar a página, ou seja, ele vai criar a página web.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;rendered&lt;/code&gt; é a página renderizada pelo o &lt;code&gt;render&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E o match é o método de busca de string em uma string.&lt;/p&gt;

&lt;p&gt;Pronto, com explicação dada, vamos rodar o teste.&lt;br&gt;
&lt;/p&gt;

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

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.55462 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 4.11 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
6 examples, 1 failure, 2 pending

Failed examples:

rspec ./spec/views/produtos/index.html.erb_spec.rb:4 &lt;span class="c"&gt;# produtos/index.html.erb Deve mostrar todos os produtos&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É obvio que falhou, porque não fizemos nada com a view e o controller.&lt;/p&gt;

&lt;p&gt;Vamos primeiro para o controller, vá para &lt;code&gt;app/controllers/produtos_controller.rb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProdutosController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@produtos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&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;Pronto, agora vamos para o &lt;code&gt;app/views/produtos/index.html.erb&lt;/code&gt; e colocar os produtos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;# app/views/produtos/index.html.erb

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@produtos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;produto&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;produto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nome&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos rodar o teste.&lt;br&gt;
&lt;/p&gt;

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

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.60784 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 5.35 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
6 examples, 0 failures, 2 pending
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sem nenhuma falha.&lt;/p&gt;

&lt;p&gt;E é isso, nós acabamos por aqui.&lt;/p&gt;

&lt;p&gt;Como eu não tenho nada o que falar, tchau!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>rspec</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testando Request em RSpec Rails</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Fri, 09 Dec 2022 10:08:58 +0000</pubDate>
      <link>https://dev.to/xandekk/testando-request-em-rspec-rails-57d9</link>
      <guid>https://dev.to/xandekk/testando-request-em-rspec-rails-57d9</guid>
      <description>&lt;p&gt;Anteriormente, nós fizemos teste para model, agora vamos fazer teste para requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o request e porque é importante testar ele.
&lt;/h2&gt;

&lt;p&gt;Antes de nós testar, primeiramente, nós temos que entender o request, que traduzindo seria, requisição.&lt;/p&gt;

&lt;p&gt;Você deve saber, eu espero, que a nossa internet funciona com base de requisição e resposta, ou seja, no meu navegador, eu estou requisitando uma página web para um servidor, e o servidor, por sua vez, vai me dar uma resposta sobre a requisição. &lt;/p&gt;

&lt;p&gt;O servidor pode aceitar a requisição, pode negar ou até mesmo pode dar erro.&lt;/p&gt;

&lt;p&gt;E é esse o nosso objetivo, nós queremos testar o que acontece quando faço requisição de formato HTML ou JSON, ou então quando acesso em uma página não autorizada, etc.&lt;/p&gt;

&lt;p&gt;Então, para começar, vamos criar uma aplicação do começo para que vocês consigam me acompanhar.&lt;/p&gt;

&lt;p&gt;A nossa ideia da aplicação é um simples blog, onde vai ter um controller e um model que é o post.&lt;/p&gt;

&lt;p&gt;Se você quiser me acompanhar, basta executar os comandos abaixo para criar a aplicação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new blog &lt;span class="nt"&gt;--skip-test&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;blog
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'gem "rspec-rails", group: [:development, :test]'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; Gemfile
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'gem "rails-controller-testing", group: :test'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; Gemfile
bundle &lt;span class="nb"&gt;install
&lt;/span&gt;rails g rspec:install
rails g resource Post titulo corpo:text
rails db:create db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto com isso, estamos pronto para testar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testando
&lt;/h2&gt;

&lt;p&gt;Beleza, para testar os requests não é tão difícil assim.&lt;/p&gt;

&lt;p&gt;vamos escrever os testes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/requests/posts_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"Posts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :request&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"GET posts"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar sucesso"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;posts_path&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&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;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"GET post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar sucesso"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Ólá"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"bla bla bala"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve ser redirecionado por não existir o post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"não existo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&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;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"GET new post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar sucesso"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;new_post_path&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&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;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"Post posts"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar created"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="n"&gt;posts_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;params: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;post: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Reza a lenda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"Ele está vindo"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:post&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;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"GET edit post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar sucesso"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Ólá"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"bla bla bala"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;edit_post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve ser redirecionado por não existir o post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;edit_post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"não existo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&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;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"PUT post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar sucesso"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Ólá"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"bla bla bala"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;put&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;params: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;post: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"sou eu o"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"tiririca"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:post&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve ser redirecionado por não existir o post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;put&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"não existo"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;params: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;post: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"sou eu o"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"tiririca"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&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;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"DELETE post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar sucesso"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Ólá"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"bla bla bala"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:redirect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve ser redirecionado por não existir o post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"não existo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&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;span class="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;É meio grandinho, mas não tem muitas diferenças em teste de model, como nós fizemos antes.&lt;/p&gt;

&lt;p&gt;Só vamos dar a atenção nesses métodos que vou citar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;get&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;post&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;put&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;have_http_status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;redirect_to&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assigns&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É só isso, porém existe mais métodos, como &lt;code&gt;patch&lt;/code&gt; etc, mas raramente você usa ele.&lt;/p&gt;

&lt;p&gt;Os primeiros quatros métodos são, obviamente, métodos de requisição HTTP, se não sabe sobre isso, eu recomendo que estude isso, porque isso é bastante importante.&lt;/p&gt;

&lt;p&gt;Não tem muito o que explicar sobre eles, pois o próprio nome diz o que eles fazem.&lt;/p&gt;

&lt;p&gt;Então vamos para &lt;code&gt;have_http_status&lt;/code&gt; e &lt;code&gt;redirect_to&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;have_http_status&lt;/code&gt; é um método para verificar se o argumento passado é equivalente ao "status code" da resposta do servidor.&lt;/p&gt;

&lt;p&gt;Enquanto o &lt;code&gt;redirect_to&lt;/code&gt; é o método para verificar se o argumento passado é equivalente ao página que o servidor redirecionou.&lt;/p&gt;

&lt;p&gt;Não tem muito segredo, se você entende de protocolo HTTP.&lt;/p&gt;

&lt;p&gt;Agora nós temos o método &lt;code&gt;assigns&lt;/code&gt;, ele relaciona com a variável da instância, ou seja, vamos pegar o nosso caso, o argumento que eu passei foi &lt;code&gt;:post&lt;/code&gt;, isso seria o equivalente o &lt;code&gt;@post&lt;/code&gt;, isso é útil para caso em que você quer o id do post, que é o nosso caso, ou então saber que ele foi criado ou atualizado com sucesso.&lt;/p&gt;

&lt;p&gt;Pronto, terminei com a explicação, agora vamos testar.&lt;br&gt;
&lt;/p&gt;

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

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.4995 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 4.57 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
13 examples, 11 failures, 2 pending

Failed examples:

rspec ./spec/requests/posts_spec.rb:5 &lt;span class="c"&gt;# Posts GET posts deve retornar sucesso&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:13 &lt;span class="c"&gt;# Posts GET post deve retornar sucesso&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:20 &lt;span class="c"&gt;# Posts GET post deve ser redirecionado por não existir o post&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:28 &lt;span class="c"&gt;# Posts GET new post deve retornar sucesso&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:36 &lt;span class="c"&gt;# Posts Post posts deve retornar created&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:49 &lt;span class="c"&gt;# Posts GET edit post deve retornar sucesso&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:56 &lt;span class="c"&gt;# Posts GET edit post deve ser redirecionado por não existir o post&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:64 &lt;span class="c"&gt;# Posts PUT post deve retornar sucesso&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:76 &lt;span class="c"&gt;# Posts PUT post deve ser redirecionado por não existir o post&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:89 &lt;span class="c"&gt;# Posts DELETE post deve retornar sucesso&lt;/span&gt;
rspec ./spec/requests/posts_spec.rb:96 &lt;span class="c"&gt;# Posts DELETE post deve ser redirecionado por não existir o post&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bem, nós esquecemos de criar as actions do controller e as  views.&lt;/p&gt;

&lt;p&gt;Vamos para &lt;code&gt;app/controller/posts_controller.rb&lt;/code&gt; e criar as actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controller/posts_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
    &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:define_post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
          &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
        &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; 

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;edit&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt; &lt;span class="n"&gt;post_params&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;post_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;posts_path&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="kp"&gt;private&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_params&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:titulo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:corpo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;define_post&lt;/span&gt;
        &lt;span class="k"&gt;begin&lt;/span&gt;
            &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordNotFound&lt;/span&gt;
            &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;posts_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :not_found&lt;/span&gt;
        &lt;span class="k"&gt;end&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;Pronto, criamos as actions, agora vamos criar as views, basta executar os comandos abaixo.&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;touch &lt;/span&gt;app/views/posts/index.html.erb app/views/posts/show.html.erb app/views/posts/new.html.erb app/views/posts/edit.html.erb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora sim, nós estamos pronto, vamos rodar o teste.&lt;br&gt;
&lt;/p&gt;

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

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.81536 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 4.77 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
13 examples, 0 failures, 2 pending
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passou.&lt;/p&gt;

&lt;p&gt;E é isso, terminamos aqui, só que não, eu estava pensando aqui, será que vale a pena fazer um teste para uma aplicação de API? Pois é útil aprender como que testa as requisições do tipo JSON.&lt;/p&gt;

&lt;p&gt;Mas não vale a pena, porque seria um copiar e colar e colocar um argumento header e testar se resposta é json.&lt;/p&gt;

&lt;p&gt;Eu só vou fazer só um teste de requisição para ter noção.&lt;/p&gt;

&lt;p&gt;Vamos para &lt;code&gt;spec/requests/post_spec.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/requests/post_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"Posts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :request&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"GET posts"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"requisição json"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar sucesso"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"ACCEPT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;posts_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;headers: &lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;

        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"application/json; charset=utf-8"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&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;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="o"&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;Se nós analisamos o teste, vai perceber que não teve muita diferença o que a gente fez anteriormente, eu passei o argumento &lt;code&gt;headers&lt;/code&gt; no &lt;code&gt;get&lt;/code&gt; e testei se o tipo de conteúdo é JSON, só isso.&lt;/p&gt;

&lt;p&gt;Se nós rodar o teste, é obvio que vai falhar, então para evitar isso, vamos para &lt;code&gt;app/controller/post_controller.rb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;

    &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="vi"&gt;@posts&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;span class="o"&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;Com isso, a nossa aplicação aceita a requisição HTML e JSON.&lt;/p&gt;

&lt;p&gt;Agora, se nós rodar o teste, vai funcionar, e isso é o suficiente para nós testar a aplicação que atende requisição json.&lt;/p&gt;

&lt;p&gt;Com isso, nós terminamos aqui.&lt;/p&gt;

&lt;p&gt;Tchau!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>rspec</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testando model em RSpec Rails.</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Thu, 08 Dec 2022 21:55:29 +0000</pubDate>
      <link>https://dev.to/xandekk/testando-o-model-em-rspec-rails-1ebd</link>
      <guid>https://dev.to/xandekk/testando-o-model-em-rspec-rails-1ebd</guid>
      <description>&lt;p&gt;Vamos aprender a testar o model em rails usando o RSpec.&lt;/p&gt;

&lt;p&gt;Mas antes de aprender a testar, vamos criar uma aplicação para ter uma visualização a nossa aplicação.&lt;/p&gt;

&lt;p&gt;Eu vou criar um simples blog, em que vai ter duas tabelas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;titulo&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;corpo&lt;/span&gt;
&lt;span class="no"&gt;Comentario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;texto&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;post_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tendo a noção da minha aplicação, vamos criar ele.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new testando_model &lt;span class="nt"&gt;--skip-test&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;testando_model
rails db:create db:migrate
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'gem "rspec-rails", group: [:development, :test]'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; Gemfile
bundle &lt;span class="nb"&gt;install
&lt;/span&gt;rails g rspec:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Primeiro vamos criar o model Post e migrar ele.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g model Post titulo corpo:text
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto com isso, nós podemos testar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testando o model
&lt;/h2&gt;

&lt;p&gt;Vamos abrir o arquivo &lt;code&gt;spec/models/post_spec.rb&lt;/code&gt; e fazer um teste simples.&lt;/p&gt;

&lt;p&gt;Então vamos fazer um teste simples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/models/post_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve criar um post"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# traduzindo isso, seria desse jeito&lt;/span&gt;
    &lt;span class="c1"&gt;# Espero que a contagem do post seja igual 1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O método &lt;code&gt;it&lt;/code&gt; permite você passe o argumento de uma string que explique o seu teste e tem que utilizar o bloco para executar o seu teste.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;expect&lt;/code&gt; recebe o argumento do valor atual, que o nosso caso é a contagem do post, e depois disso, tem o &lt;code&gt;to&lt;/code&gt; que tenta comparar o valor atual de acordo com primeiro argumento, que é o método &lt;code&gt;equal&lt;/code&gt; que contém o valor esperado.&lt;/p&gt;

&lt;p&gt;Isso seria a mesma lógica que esse código que eu vou fazer, só que o meu código não foi feito para teste.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bem, vamos rodar o teste.&lt;br&gt;
&lt;/p&gt;

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

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.08076 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 3.83 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
1 example, 0 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O teste passou, isso significa que pelos menos é possível criar um post.&lt;/p&gt;

&lt;p&gt;Agora vamos nos aprofundar um pouco.&lt;/p&gt;

&lt;p&gt;Eu quero testar que não é possível criar um post sem título e corpo.&lt;/p&gt;

&lt;p&gt;Também quero que tenha limite de caracteres do título e do corpo.&lt;/p&gt;

&lt;p&gt;Então eu vou mudar o primeiro teste para que possa adaptar as condições que citei em cima e adiciona mais testes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/models/post_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve ser valido um post com titulo e corpo"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Instalando rpsec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"Lero lero"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="c1"&gt;# espero que o post seja valido&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido sem o titulo"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"Lero lero"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="c1"&gt;# espero que o post não seja valido&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido sem um titulo"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"instalando rpsec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="c1"&gt;# espero que o post não seja valido&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido com um titulo maior que 50 caracteres"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="c1"&gt;# espero que o post não seja valido&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido com um corpo maior que 500 caracteres"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Como não ser burro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"o"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;501&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="c1"&gt;# espero que o post não seja valido&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;Pronto, Vamos rodar o teste.&lt;br&gt;
&lt;/p&gt;

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

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.15579 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 4.44 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
5 examples, 4 failures

Failed examples:

rspec ./spec/models/post_spec.rb:13 &lt;span class="c"&gt;# Post não deve ser valido sem o titulo&lt;/span&gt;
rspec ./spec/models/post_spec.rb:22 &lt;span class="c"&gt;# Post não deve ser valido sem um titulo&lt;/span&gt;
rspec ./spec/models/post_spec.rb:31 &lt;span class="c"&gt;# Post não deve ser valido com um titulo maior que 50 caracteres&lt;/span&gt;
rspec ./spec/models/post_spec.rb:38 &lt;span class="c"&gt;# Post não deve ser valido com um corpo maior que 500 caracteres&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É, os testes falharam, isso significa que nossa aplicação não está seguindo do jeito que nós queríamos.&lt;/p&gt;

&lt;p&gt;Então, vamos consertar a nossa aplicação.&lt;/p&gt;

&lt;p&gt;Primeiro, vamos para o arquivo &lt;code&gt;app/models/post.rb&lt;/code&gt; e adicionar algumas validação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/post.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:titulo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;length: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;maximum: &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:corpo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;length: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;maximum: &lt;/span&gt;&lt;span class="mi"&gt;500&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;Agora, os testes devem passar.&lt;br&gt;
&lt;/p&gt;

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

.....

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.08726 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 4.24 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
5 examples, 0 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ta dã, os testes passaram, isso significa que no minimo, o seu código é minimamente confiável.&lt;/p&gt;

&lt;p&gt;Mas vamos organizar ele, pois está feio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/models/post_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="ss"&gt;titulo: &lt;/span&gt;&lt;span class="s2"&gt;"Instalando rpsec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;corpo: &lt;/span&gt;&lt;span class="s2"&gt;"Lero lero"&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"é valido"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve ser valido um post com titulo e corpo"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"não está preenchido os campos"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido sem o titulo"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;titulo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido sem um titulo"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;corpo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"passou do limite de caracteres"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido com um titulo maior que 50 caracteres"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;titulo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;  &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ser valido com um corpo maior que 500 caracteres"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;corpo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"o"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;501&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
    &lt;span class="k"&gt;end&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;Você pode notar algumas palavras novas nesse código, mas não se preocupa que eu vou explicar cada uma dela.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explicando o subject e context
&lt;/h2&gt;

&lt;p&gt;Primeiro, vamos começar com &lt;code&gt;subject&lt;/code&gt;, nós podemos dizer que é o objeto que está sendo testado, que o nosso caso seria o objeto da classe Post.&lt;/p&gt;

&lt;p&gt;Com isso, nós podemos usá-la em qualquer parte do código.&lt;/p&gt;

&lt;p&gt;Agora vamos falar sobre o &lt;code&gt;context&lt;/code&gt;, como o nome diz, é o contexto do bloco.&lt;/p&gt;

&lt;p&gt;No primeiro &lt;code&gt;context&lt;/code&gt;, eu defino que aquele bloco, só tem validação correta.&lt;/p&gt;

&lt;p&gt;Enquanto o segundo &lt;code&gt;context&lt;/code&gt; foi definido que aquele bloco só tem validação incorreta por falta de valores.&lt;/p&gt;

&lt;p&gt;E o terceiro, a mesma coisa que segundo, porém com ultrapassagem do limite de caracteres.&lt;/p&gt;

&lt;p&gt;E é só isso.&lt;/p&gt;

&lt;p&gt;Agora vamos testar o código&lt;br&gt;
&lt;/p&gt;

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

.....

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.07729 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 3.84 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
5 examples, 0 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Está funcionando.&lt;/p&gt;

&lt;p&gt;Vamos tentar adicionar um teste que vai falhar com certeza absoluta.&lt;/p&gt;

&lt;p&gt;Eu quero testar se o post tem comentário e quantos ele tem.&lt;/p&gt;

&lt;p&gt;Eu vou omitir os outros testes para ocupar menos espaços.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# spec/models/post_spec.rb&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"#tem_quantos_comentario"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve ter dois comentario"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;Comentario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;texto: &lt;/span&gt;&lt;span class="s2"&gt;"Foda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;post: &lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Comentario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;texto: &lt;/span&gt;&lt;span class="s2"&gt;"Gostei"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;post: &lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tem_quantos_comentario&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"não deve ter nenhum comentario"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tem_quantos_comentario&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"#tem_comentario?"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar true"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;Comentario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;texto: &lt;/span&gt;&lt;span class="s2"&gt;"Foda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;post: &lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tem_comentario?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be_truthy&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"deve retornar false"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tem_comentario?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be_falsey&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;Vcoê pode ter percebido esse &lt;code&gt;#&lt;/code&gt; antes do nome no context.&lt;/p&gt;

&lt;p&gt;Isso é um forma de dizer que esse contexto está testando o método da instância. Se você colocar um &lt;code&gt;.&lt;/code&gt; antes do método, você está dizendo que o contexto é testar o método da classe.&lt;/p&gt;

&lt;p&gt;Se nós rodar o código, obviamente vai falhar, porque ainda não existe o model Comentario e os métodos, então vamos criar eles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g model Comentario texto post:references
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos criar os métodos e colocar associação do comentário com post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/post.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:comentarios&lt;/span&gt;

  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:titulo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;length: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;maximum: &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:corpo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;length: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;maximum: &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tem_quantos_comentario&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;comentarios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tem_comentario?&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;comentarios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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 testar o código.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;*&lt;/span&gt;.........

Pending: &lt;span class="o"&gt;(&lt;/span&gt;Failures listed here are expected and &lt;span class="k"&gt;do &lt;/span&gt;not affect your suite&lt;span class="s1"&gt;'s status)

  1) Comentario add some examples to (or delete) /tmp/testando_model/spec/models/comentario_spec.rb
     # Not yet implemented
     # ./spec/models/comentario_spec.rb:4


Finished in 0.19358 seconds (files took 3.74 seconds to load)
10 examples, 0 failures, 1 pending
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Está tudo funcionando.&lt;/p&gt;

&lt;p&gt;Bem, eu não vou testar o comentário, porque não seria muito diferente do teste Post.&lt;/p&gt;

&lt;p&gt;Então eu deixo você fazer o resto.&lt;/p&gt;

&lt;p&gt;Pronto, com isso, nós podemos dar a segurança aos nossos models com esses testes.&lt;/p&gt;

&lt;p&gt;É claro que os nossos testes feito aqui não o suficiente.&lt;/p&gt;

&lt;p&gt;Nós temos que testar a associação, remoção de dados de banco de dados etc.&lt;/p&gt;

&lt;p&gt;No próximo post, eu vou testar os requests.&lt;/p&gt;

&lt;p&gt;E é isso, Tchau!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>learning</category>
    </item>
    <item>
      <title>Instalando Rspec em Rails 7</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Thu, 08 Dec 2022 21:53:38 +0000</pubDate>
      <link>https://dev.to/xandekk/instalando-rspec-em-rails-7-313l</link>
      <guid>https://dev.to/xandekk/instalando-rspec-em-rails-7-313l</guid>
      <description>&lt;p&gt;Para que o seu código seja bom, é necessário que seu código seja testado, se não, o código não é bom, mesmo que que esteja organizado, legível, etc.&lt;/p&gt;

&lt;p&gt;Então para testar os nossos códigos, nós vamos instalar a Rspec em Rails.&lt;/p&gt;

&lt;p&gt;Antes de começar, vamos criar uma aplicação rápida.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new testando_codigo &lt;span class="nt"&gt;--skip-test&lt;/span&gt;
bin/rails db:create db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comando &lt;code&gt;--skip-test&lt;/code&gt;, serve para não criar o diretório &lt;code&gt;test/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pronto, agora com aplicação criada, vamos colocar a gem.&lt;/p&gt;

&lt;p&gt;Abra no arquivo Gemfile, e coloque a &lt;code&gt;gem "rspec-rails"&lt;/code&gt; no grupo de desenvolvimento e teste, como você pode ver embaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:development&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"rspec-rails"&lt;/span&gt;
&lt;span class="k"&gt;end&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 executa o &lt;code&gt;bundle install&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;bundle &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, agora o rspec está instalado na aplicação, porém ainda falta uma coisa, os arquivos.&lt;/p&gt;

&lt;p&gt;Para gerar os arquivos de rpsec, rode 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;rails generate rspec:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso vai criar o diretório &lt;code&gt;spec/&lt;/code&gt;, e alguns arquivos necessários para teste.&lt;/p&gt;

&lt;p&gt;Com isso, nós estamos pronto para testar.&lt;/p&gt;

&lt;p&gt;Eu não vou mostrar como que testa, mas eu farei uma série de postagem de teste, como 'model', 'request', 'view', etc.&lt;/p&gt;

&lt;p&gt;Bem, vamos continuar.&lt;/p&gt;

&lt;p&gt;Vamos gerar um scaffold, para livrar o trabalho de escrever o teste.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g scaffold usuario nome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto com scaffold gerado, execute o &lt;code&gt;rspec&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;rspec
&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
Finished &lt;span class="k"&gt;in &lt;/span&gt;1.34 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 7.56 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
27 examples, 0 failures, 14 pending
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, com rspec instalado, você pode testar que o seu código.&lt;/p&gt;

&lt;p&gt;Então é isso, tchau!&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
  </channel>
</rss>
