<?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: Jony Hayama</title>
    <description>The latest articles on DEV Community by Jony Hayama (@jonyhayama).</description>
    <link>https://dev.to/jonyhayama</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%2F388160%2Fe2d5f777-c2d4-4843-a8a5-25d535b97805.jpeg</url>
      <title>DEV Community: Jony Hayama</title>
      <link>https://dev.to/jonyhayama</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonyhayama"/>
    <language>en</language>
    <item>
      <title>Otimizando um campo de Autocomplete com Postgres e Rails</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Mon, 14 Nov 2022 17:49:42 +0000</pubDate>
      <link>https://dev.to/jonyhayama/otimizando-um-campo-de-autocomplete-com-postgres-e-rails-47h</link>
      <guid>https://dev.to/jonyhayama/otimizando-um-campo-de-autocomplete-com-postgres-e-rails-47h</guid>
      <description>&lt;p&gt;Sabe quando você e seu time erra a mão na hora de estimar uma task?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Task: Criar campo autocomplete que deve sugerir "tags" para o usuário&lt;br&gt;
Estimado em: 3SP&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assim que comecei a trabalhar task ouvi o Faustão falando no meu ouvido: "E-r-r-r-r-r-oooouu".&lt;/p&gt;

&lt;p&gt;Existem inúmeras otimizações que podem ser feitas em um campo desses que fiquei até desnorteado.&lt;/p&gt;

&lt;p&gt;Gostaria de compartilhar um pouco do que acabei produzindo nessa task. Estou longe de dizer que esta é a melhor forma possível de fazer um campo como esse, mas acredito que é um bom ponta-pé inicial.&lt;/p&gt;

&lt;p&gt;Para facilitar a conversa e deixar esse post mais interessante, ao invés de buscar tags, vamos buscar personagens da Marvel.&lt;/p&gt;

&lt;p&gt;Se quiser dar uma olhada no resultado final, acessa aí:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exemplo Funcional: &lt;a href="https://marvel.apps.jony.dev/"&gt;https://marvel.apps.jony.dev/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Código-fonte: &lt;a href="https://github.com/jonyhayama/find-marvel-characters"&gt;https://github.com/jonyhayama/find-marvel-characters&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O que eu fiz no Postgres
&lt;/h2&gt;

&lt;p&gt;Se você ainda não conheçe, a Marvel fornece uma API para podermos coletar dados: &lt;a href="https://developer.marvel.com/"&gt;https://developer.marvel.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como meu objetivo aqui é falar sobre o Postgres, fiz alguns requests para a API, salvei os dados que me interessam em um CSV e criei um seed para importar esses dados no banco.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Se quiser, pode baixar o repositório do projeto e rodar &lt;code&gt;rails db:seed&lt;/code&gt;, o CSV está commitado 😜.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos considerar, portanto, que temos uma tabela chamada &lt;code&gt;characters&lt;/code&gt; e que precisamos fazer uma busca na coluna &lt;code&gt;name&lt;/code&gt; para devolver o resultado dessa pesquisa para o usuário.&lt;/p&gt;

&lt;p&gt;Minha primeira ideia foi bem 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="no"&gt;Character&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="s1"&gt;'name ILIKE ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&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;:query&lt;/span&gt;&lt;span class="p"&gt;]&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;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# SELECT "characters"."name" FROM "characters" WHERE (name ILIKE '%Iron Man%');&lt;/span&gt;
&lt;span class="c1"&gt;# Execution Time: 2.995 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ OBS:&lt;/strong&gt; &lt;br&gt;
1 - Vou sempre deixar query gerada pelo ActiveRecord comentada em baixo da instrução para facilitar o papo 😜&lt;br&gt;
2 - Considere que estamos em um Controller e que &lt;code&gt;params[:query] = 'Iron Man'&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Logo de cara temos uma otimização a fazer: Em linhas gerais, o Postgres é mais performático fazendo comparações com &lt;code&gt;LIKE&lt;/code&gt; do que &lt;code&gt;ILIKE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nós conseguimos exatamente o mesmo resultado, porém com um tempo de execução menor, se escrevermos:&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;Character&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="s1"&gt;'lower(name) LIKE ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&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;:query&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&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;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# SELECT "characters"."name" FROM "characters" WHERE (lower(name) LIKE '%iron man%');&lt;/span&gt;
&lt;span class="c1"&gt;# Execution Time: 1.012 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A próxima otimização seria criar um índice para a coluna &lt;code&gt;name&lt;/code&gt; que está sendo alvo da busca.&lt;/p&gt;

&lt;p&gt;Eu já estava pronto para criar uma migration com &lt;code&gt;add_index :characters, :name&lt;/code&gt; quando descobri que é possível criar &lt;a href="https://www.postgresql.org/docs/current/indexes-expressional.html"&gt;índices baseados em expressões&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Algo simples como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;index_characters_lower_name&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que, naturalmente, traria ainda mais performance já que estamos fazendo a busca baseado exatamente nessa expressão.&lt;/p&gt;

&lt;p&gt;Foi então que, antes mesmo de ter tempo de implementar esse índice, o StackOverflow me indagou...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;StackOverflow:&lt;/strong&gt; Já ouviu falar da palavra de &lt;a href="https://www.postgresql.org/docs/current/pgtrgm.html"&gt;pg_trgm&lt;/a&gt;?&lt;br&gt;
&lt;strong&gt;Eu:&lt;/strong&gt; Caramba, como será que se fala "trgm"? &lt;br&gt;
&lt;strong&gt;Documentação do Postgres:&lt;/strong&gt; it's "Trigram"&lt;br&gt;
&lt;strong&gt;Google Translate:&lt;/strong&gt; "Trigram" = "Trigrama" em terras tupiniquins.&lt;br&gt;
&lt;strong&gt;Eu:&lt;/strong&gt; Mas o que diabos é um trigrama?&lt;br&gt;
&lt;strong&gt;Google:&lt;/strong&gt; vocábulo de três letras.&lt;br&gt;
&lt;strong&gt;Eu:&lt;/strong&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EkklpSYV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media.tenor.com/QcrcBpXx3qYAAAAC/boy-kid.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EkklpSYV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media.tenor.com/QcrcBpXx3qYAAAAC/boy-kid.gif" alt="que joia" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lendo a documentação com um pouco mais de carinho e, sem entrar em muitos detalhes (até porque eu acho que nem conseguiria), entendi que:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Usando Trigramas, o Postgres consegue gerar um valor numérico para dizer qual é a similaridade entre dois termos, sendo 0 completamente diferente e 1 exatamente igual.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Isso quer dizer que, com uma simples ordenação, eu poderia retornar sugestões de personagens com mais assertividade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&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;similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'iron man'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%iron man%'&lt;/span&gt; 
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Corri, abri o &lt;code&gt;rails dbconsole&lt;/code&gt;, colei a query e...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR:  function similarity(character varying, unknown) does not exist
LINE 3:   similarity(name, 'iron man') AS score
          ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De volta à documentação, descobri que é necessário habilitar a extesão primeiro 🙈... então criei uma migration rapidinho:&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;EnablePgTrgmExtension&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&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;change&lt;/span&gt;
    &lt;span class="n"&gt;enable_extension&lt;/span&gt; &lt;span class="s1"&gt;'pg_trgm'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# CREATE EXTENSION pg_trgm;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, com a extensão ativada, query executada, temos o seguinte resultado:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Ultimate)&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Marvel Heroes)&lt;/td&gt;
&lt;td&gt;0.42857143&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man/Tony Stark (MAA)&lt;/td&gt;
&lt;td&gt;0.4090909&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Marvel War of Heroes)&lt;/td&gt;
&lt;td&gt;0.32142857&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;td&gt;0.31034482&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (LEGO Marvel Super Heroes)&lt;/td&gt;
&lt;td&gt;0.28125&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M.O.D.O.K. (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;td&gt;0.25714287&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;War Machine (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;td&gt;0.23076923&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crimson Dynamo (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;td&gt;0.20930232&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Repare que temos uma ordenação bem diferente em relação à nossa primeira query:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Crimson Dynamo (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (LEGO Marvel Super Heroes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Marvel Heroes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Marvel War of Heroes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man (Ultimate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iron Man/Tony Stark (MAA)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M.O.D.O.K. (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;War Machine (Iron Man 3 - The Official Game)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Você deve estar se perguntando por que comecei a falar da ordenação antes de criar o índice né?&lt;/p&gt;

&lt;p&gt;Simples: podemos criar um índice para o trigrama 😜&lt;/p&gt;

&lt;p&gt;Então, finalmente, bora para a migration:&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;AddCharacterNameLowerTagIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&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;up&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"CREATE INDEX index_characters_lower_name ON characters USING gin (lower(name) gin_trgm_ops);"&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;down&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"DROP INDEX index_characters_lower_name;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  O que eu fiz no Rails
&lt;/h2&gt;

&lt;p&gt;Agora que temos uma query bacana, é só uma questão de reescrevê-la utilizando o ActiveRecord, certo?&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="n"&gt;query&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;:query&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;
&lt;span class="no"&gt;Character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"name, similarity(name, '&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;') AS score"&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="s1"&gt;'lower(name) LIKE ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;query&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;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'score DESC'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤔 Ficou meio grande né?&lt;/p&gt;

&lt;p&gt;Sem contar que, naturalmente, a gente não deve simplesmente concatenar um parâmetro enviado pelo usuário na nossa query...&lt;/p&gt;

&lt;p&gt;Infelizmente o &lt;code&gt;select()&lt;/code&gt; não tem a mesma sanitização que o &lt;code&gt;where()&lt;/code&gt; que te permite fazer parameter binding.&lt;/p&gt;

&lt;p&gt;Para driblar esse problema, podemos usar um método chamado &lt;code&gt;sanitize_sql_array()&lt;/code&gt; para nos auxiliar:&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="n"&gt;query&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;:query&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;
&lt;span class="no"&gt;Character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&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;Base&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sanitize_sql_array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"name, similarity(name, ?) AS score"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&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="s1"&gt;'lower(name) LIKE ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;query&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;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'score DESC'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CT98Z_6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media.tenor.com/jZ3P8DPb_YEAAAAd/tava-b%25C3%25A3o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CT98Z_6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media.tenor.com/jZ3P8DPb_YEAAAAd/tava-b%25C3%25A3o.gif" alt="parece que piorou" width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🤔 Como estamos acessando &lt;code&gt;ActiveRecord::Base&lt;/code&gt;, há grandes chances de isso ficar melhor no Model...vamos transformar isso num scopo?&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/character.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Character&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;scope&lt;/span&gt; &lt;span class="ss"&gt;:order_by_name_similarity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sanitize_sql_array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"similarity(name, ?) AS score"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"score DESC"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repare que optei por deixar o padrão &lt;code&gt;select(*)&lt;/code&gt; ao invés de &lt;code&gt;select(:name)&lt;/code&gt;, dessa forma temos o objeto completo e podemos utilizar outros dados no retorno (se necessário).&lt;/p&gt;

&lt;p&gt;Agora a consulta em si fica bem mais 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="n"&gt;query&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;:query&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;
&lt;span class="no"&gt;Character&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="s1"&gt;'lower(name) LIKE ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;query&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;order_by_name_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# SELECT *, similarity(name, 'iron man') AS score FROM "characters" WHERE (lower(name) LIKE '%iron man%') ORDER BY score DESC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acho interessante também adicionar um &lt;code&gt;limit(10)&lt;/code&gt; para não ter uma lista muito grande de opções aparecendo para o usuário.&lt;/p&gt;

&lt;p&gt;No final do dia, o método no Controller ficou assim:&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;index&lt;/span&gt;
  &lt;span class="n"&gt;query&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;:query&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;
  &lt;span class="vi"&gt;@characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Character&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="s1"&gt;'lower(name) LIKE ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;query&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;order_by_name_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# SELECT *, similarity(name, 'iron man') AS score FROM "characters" WHERE (lower(name) LIKE '%iron man%') ORDER BY score DESC LIMIT 10&lt;/span&gt;

  &lt;span class="n"&gt;expires_in&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minutes&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repare que também adicionei um &lt;code&gt;expires_in 10.minutes&lt;/code&gt; para o navegador pode cachear essa resposta.&lt;/p&gt;

&lt;p&gt;É claro que cada caso é um caso e - talvez - 10 minutos não seja a melhor estratégia, mas meu ponto é: é importante ter alguma estratégia de cache.&lt;/p&gt;




&lt;p&gt;Não sei você, mas pra mim tudo isso passou longe dos 3SPs estimados inicialmente. Especialmente se considerarmos que ainda falta fazer o front.&lt;/p&gt;

&lt;p&gt;Para falar a verdade mesmo, eu dei uma ajustada na história... quando disse que "antes mesmo de criar o índice"... convenhamos... você sabe que eu fiz, desfiz e fiz de novo né? 😜&lt;/p&gt;

&lt;p&gt;Só organizei a história de uma forma mais cronológica, mas rolou muita pesquisa, teste e re-teste até chegar nessa nessa solução.&lt;/p&gt;

&lt;p&gt;E olha que só falamos de Back...vou deixar o Front para um próximo post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PS:&lt;/strong&gt; Não encontrei um lugar no meio do texto, mas queria deixar uma queryzinha de presente que talvez lhe seja útil:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;indexname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indexdef&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pg_indexes&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;tablename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'characters'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ess query lista os índices de uma determinada tabela.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EM TEMPO:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quando comecei a trabalhar no front, comecei a tentar faze a busca por outras personagens.&lt;/p&gt;

&lt;p&gt;Foi nessa que eu descobri que o nome oficial é "Spider-man". Não é "Spider man", nem "spiderman"...&lt;/p&gt;

&lt;p&gt;Para a busca por "Spider man", podemos fazer um mini-hack rapidinho:&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="n"&gt;query&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;:query&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/ /&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Já para "spiderman" acho que a coisa complica mais e - talvez - &lt;code&gt;pg_trgm&lt;/code&gt; não seja o ideal...&lt;/p&gt;

&lt;p&gt;É nessa hora que ferramentas como Elastic Search, Algolia e afins podem ser aliadas...mas tudo tem seu custo (seja financeiro ou de implementação) 😜&lt;/p&gt;




&lt;p&gt;Tem ideias, críticas ou sugestões? comenta aí :D&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>braziliandevs</category>
      <category>rails</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Acessando o "compartilhar" nativo, vulgo Web-Share, em VanillaJS e Vue</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Thu, 11 Aug 2022 19:09:09 +0000</pubDate>
      <link>https://dev.to/jonyhayama/acessando-o-compartilhar-nativo-vulgo-web-share-em-vanillajs-e-vue-1n1i</link>
      <guid>https://dev.to/jonyhayama/acessando-o-compartilhar-nativo-vulgo-web-share-em-vanillajs-e-vue-1n1i</guid>
      <description>&lt;p&gt;Nessa semana estive trabalhando em uma demanda simples de um cliente Freela.&lt;/p&gt;

&lt;p&gt;O projeto consiste em um daqueles formulários interativos que você responde X perguntas e tem um resultado no final, vulgo, um Quiz.&lt;/p&gt;

&lt;p&gt;A ideia é que o resultado fosse compartilhado no Insta com a hashtag de uma campanha para que o usuário pudesse participar de uma promoção.&lt;/p&gt;

&lt;p&gt;Meu desafio em si foi descobrir como fazer um botão "compartilhar" desses. O Facebook tem um "widget" que é só copiar, colar e pronto. Não encontrei nada similar para o Insta...&lt;/p&gt;

&lt;p&gt;Foi então que me veio na cabeça a ideia de tentar utilizar a UI nativa do smartphone do usuário. Afinal, cada usuário já está acostumado a utilizar essa interface em inúmeras operações de compartilhar que são feitas todos os dias.&lt;/p&gt;

&lt;p&gt;📖 Parti para a pesquisa e encontrei a tal da API do Web Share.&lt;/p&gt;

&lt;p&gt;Segundo a &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/API/Navigator/share"&gt;documentação do MDN&lt;/a&gt;, até o presente momento, o suporte ainda é parcial, mas nos pareceu uma solução bastante viável dado o nosso público-alvo.&lt;/p&gt;

&lt;p&gt;Existem ainda algumas restrições adicionais como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O site precisa ser acessado via HTTPS&lt;/li&gt;
&lt;li&gt;O recurso precisa ser invocado por uma ação direta do usuário&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTTPs é super fácil com o &lt;a href="https://letsencrypt.org/"&gt;Let's Encrypt&lt;/a&gt; 🙌 e, de fato, queríamos que o usuário clicasse em "compartilhar" para poder enviar nossa imagem, então, até aqui, tudo certo!&lt;/p&gt;

&lt;p&gt;Antes de seguir, criei uma funçãozinha para não ter que ficar copiando e colando toda hora (Let's keep it DRY 😜):&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/NWYKmjL?height=600&amp;amp;default-tab=js&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Com a função no jeito, vamos começar a brincadeira compartilhando um &lt;strong&gt;link&lt;/strong&gt; só para esquentar os motores:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/NWYKmbB?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Naturalmente que, no Insta, faz mais sentido compartilhar uma imagem. Portanto precisamos passar a utilizar a propriedade &lt;code&gt;files&lt;/code&gt; que espera um &lt;code&gt;array&lt;/code&gt; de &lt;code&gt;File&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O primeiro exemplo que encontrei para gerar esse &lt;code&gt;array&lt;/code&gt;, foi o de simplesmente ler o resultado de um determinado input:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/KKoPYqE?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;OBS:&lt;/strong&gt; Inicialmente tentei ativar o WebShare no evento &lt;code&gt;change&lt;/code&gt; do &lt;code&gt;input&lt;/code&gt;, mas nem sempre isso foi considerado um "user gesture", por isso precisei adicionar o botão. Se tiver interesse em validações bem detalhadas e outros possíveis cenários, da uma conferida &lt;a href="https://w3c.github.io/web-share/demos/share-files.html"&gt;nesse exemplo&lt;/a&gt; da W3C.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Funciona até que legal, mas a minha imagem estava em um servidor e não no dispositivo do usuário...&lt;/p&gt;

&lt;p&gt;De certa forma, eu precisava converter uma URL em um &lt;code&gt;File&lt;/code&gt;, o que (para a minha surpresa) pode ser feito facilmente utilizando o &lt;code&gt;fetch&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/xxWxXPP?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Depois que consegui organizar minha lógica foi hora de levar isso para o Vue, que é o framework utilizado no projeto.&lt;/p&gt;

&lt;p&gt;Para isso, optei por utilizar uma biblioteca chamada &lt;a href="https://vueuse.org/core/useShare/"&gt;VueUse&lt;/a&gt; que, dentre outras coisas, leva a reatividade para o &lt;code&gt;shareObj&lt;/code&gt; de uma forma bem interessante.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/vitejs-vite-twz2xk?file=src%2Fcomponents%2FWebShare.vue" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Daí para frente foi só &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt; e &lt;code&gt;npm run build&lt;/code&gt; 🥳&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>vue</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Mini-hack para acessar seu Banco de Dados (Postgres) do Heroku com Rails localmente</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Mon, 11 Jul 2022 18:41:46 +0000</pubDate>
      <link>https://dev.to/jonyhayama/mini-hack-para-acessar-seu-banco-de-dados-postgres-do-heroku-com-rails-localmente-3mfn</link>
      <guid>https://dev.to/jonyhayama/mini-hack-para-acessar-seu-banco-de-dados-postgres-do-heroku-com-rails-localmente-3mfn</guid>
      <description>&lt;p&gt;Existem coisas que, de tão simples, são geniais. Essa ideia chegou até mim através do comentário de colega, um herói que não usa capa. Não é nada revolucionário, mas é algo que me deixou com a sensação de "por que eu nunca fiz isso antes?".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;ATENÇÃO:&lt;/strong&gt; Isso que vou compartilhar é um hackzinho, um "recurso técnico", no português claro: uma &lt;strong&gt;gambiarra&lt;/strong&gt;. E - como toda gambiarra - precisa ter &lt;strong&gt;cuidado na hora de usar&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Disclaimer feito, bora lá.&lt;/p&gt;

&lt;p&gt;Em anos de desenvolvimento, eu sempre me condicionei a pensar "vou copiar o banco de &lt;em&gt;staging&lt;/em&gt; para ter uma massa de dados". Muitos desenvolvedores utilizam Seeds para esse propósito e fazem um ótimo trabalho com isso.&lt;/p&gt;

&lt;p&gt;Sempre que surge um bug, meu &lt;em&gt;mindset&lt;/em&gt; é: vamos descobrir como replicar isso em &lt;em&gt;staging&lt;/em&gt;, para poder copiar o banco e investigar localmente.&lt;/p&gt;

&lt;p&gt;Nenhum problema até que você tenha um banco enorme. Daqueles que você precisa ir fazer outra coisa enquanto está baixando e restaurando. É um tempo em que você pode dar uma olhada no &lt;em&gt;backlog&lt;/em&gt;, ou talvez dar uma olhada nos PRs dos colegas, ou simplesmente ir tomar café... Mas convenhamos, seria mais produtivo já poder codar.&lt;/p&gt;

&lt;p&gt;Bom, eis que eu estava copiando um banco monstruoso e comentei com o meu colega...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Eu&lt;/strong&gt;: putz, tô baixando o banco, parece que vai demorar... 😩&lt;br&gt;
&lt;strong&gt;Colega&lt;/strong&gt;: porque você não conecta direto em &lt;em&gt;staging&lt;/em&gt;?&lt;br&gt;
&lt;strong&gt;Eu&lt;/strong&gt;: como assim? 🤔&lt;br&gt;
&lt;strong&gt;Colega&lt;/strong&gt;: se o banco é enorme e você não vai editar nada, conecta direto em &lt;em&gt;staging&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Eu&lt;/strong&gt;: como faço isso?&lt;br&gt;
&lt;strong&gt;Colega&lt;/strong&gt;:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;heroku config:get DATABASE_URL &lt;span class="nt"&gt;-a&lt;/span&gt; your-app&lt;span class="sb"&gt;`&lt;/span&gt; rails s
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Eu&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w1hxOMqZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py9ri5ihn469gc9gsxhm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w1hxOMqZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py9ri5ihn469gc9gsxhm.gif" alt="chocado" width="640" height="640"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simples assim, posso adicionar um &lt;code&gt;byebug&lt;/code&gt; onde eu quiser para investigar o problema 🥳!&lt;/p&gt;

&lt;p&gt;Se você também usa o Heroku, tenho certeza que já tropeçou no comando &lt;code&gt;heroku config&lt;/code&gt; em algum momento para trabalhar com variáveis de ambiente. Eu mesmo já mencionei ele no primeiro artigo que escrevi no &lt;a href="https://dev.to/jonyhayama/como-clonar-um-app-no-heroku-3mao"&gt;dev.to&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Eu já até cheguei a usar, para copiar uma &lt;code&gt;ENV&lt;/code&gt; que estava em staging para o meu &lt;code&gt;.env.local&lt;/code&gt;. Já até vi ele jogado em um &lt;code&gt;makefile&lt;/code&gt; em um script que já não lembro mais o que fazia...&lt;/p&gt;

&lt;p&gt;Mas confesso que essa ideia nunca tinha me passado pela cabeça 🤦‍♂️&lt;/p&gt;

&lt;p&gt;O mais interessante é que não precisamos nos limitar ao &lt;code&gt;rails s&lt;/code&gt;...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;heroku config:get DATABASE_URL &lt;span class="nt"&gt;-a&lt;/span&gt; your-app&lt;span class="sb"&gt;`&lt;/span&gt; rails c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E nem sequer ao Rails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;heroku config:get DATABASE_URL &lt;span class="nt"&gt;-a&lt;/span&gt; your-app&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, se você, assim como eu, é bastante preguiçoso, pode criar aliases e funções no seu &lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;stgdburl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"heroku config:get DATABASE_URL -a your-app"&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;stgdb&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;stgdburl&lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🧙 Magicamente os comandos passam a ser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;stgdb rails s
stgdb rails c
psql &lt;span class="nt"&gt;-d&lt;/span&gt; stgdburl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;ATENÇÃO:&lt;/strong&gt; Antes de sair correndo e fuçando tudo isso, convém dar uma olhadinha no seu &lt;code&gt;config/database.yml&lt;/code&gt; e dar uma lida na &lt;a href="https://edgeguides.rubyonrails.org/configuring.html#configuring-a-database"&gt;documentação do rails&lt;/a&gt;.&lt;br&gt;
É importante saber como está a sua configuração para saber como a aplicação irá se comportar com a presença do &lt;code&gt;DATABASE_URL&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RZwNcyKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33nnwtzcu360wsacoq8h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RZwNcyKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33nnwtzcu360wsacoq8h.png" alt="Com grandes poderes vêm grandes responsabilidades" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como você já deve ter percebido, da para conectar em qualquer banco, inclusive prod.&lt;/p&gt;

&lt;p&gt;Então, cuidado 😜&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>heroku</category>
      <category>rails</category>
    </item>
    <item>
      <title>Reticências com tooltip automático (Vue)</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Mon, 13 Jun 2022 17:20:00 +0000</pubDate>
      <link>https://dev.to/jonyhayama/reticencias-com-tooltip-automatico-vue-40pj</link>
      <guid>https://dev.to/jonyhayama/reticencias-com-tooltip-automatico-vue-40pj</guid>
      <description>&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;🔗 Resultado final&lt;/p&gt;

&lt;h2&gt;
  
  
  A história
&lt;/h2&gt;

&lt;p&gt;Hoje a responsável pela UX da empresa onde trabalho nos trouxe uma solicitação bem simples:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"quando um determinado texto for muito grande, exiba somente as duas primeiras linhas e, quando o usuário passar o mouse, mostre a dica de tela com o texto completo".&lt;/p&gt;

&lt;p&gt;-- &lt;cite&gt;UX da Empresa&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Num primeiro momento pensamos em limitar o número de caracteres e fazer com o bom velho &lt;code&gt;substring&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/QWQZZRG?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Mas aí veio a pergunta "quantos caracteres perfazem duas linhas?" 🤔&lt;/p&gt;

&lt;p&gt;Fica bastante difícil definir essa quantidade quando não estamos utilizando uma fonte monoespaçada... E mesmo assim, fica bastante complicado se trouxermos a responsividade para a equação...&lt;/p&gt;

&lt;p&gt;Pensando nisso, resolvemos nos adaptar e utilizar o elegantíssimo &lt;code&gt;line-clamp&lt;/code&gt; do CSS:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/JjpmeKx?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;🔀 PR criado.&lt;/p&gt;

&lt;p&gt;🚀 Solução enviada para &lt;em&gt;staging&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;🤞 Só falta aprovação de QA e...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Seria interessante que a dica de tela fosse exibida somente se o texto tiver sido truncado".&lt;/p&gt;

&lt;p&gt;-- &lt;cite&gt;QA da empresa&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;E volta o cão arrependido para pensar mais um pouco sobre o assunto 😢.&lt;/p&gt;

&lt;p&gt;Revisitando a solução baseada em quantidade de caracteres, poderíamos resolver assim:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/KKQGrmy?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Mas eu sou teimoso.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;line-clamp&lt;/code&gt; é mais elegante. Reflete melhor a problemática de exibir &lt;em&gt;por quantidade de linhas&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Depois de pesquisar um pouco, encontrei uma forma de avaliar se o texto foi truncado baseado no tamanho do container utilizando as propriedades &lt;code&gt;scrollWidth&lt;/code&gt; e &lt;code&gt;scrollHeight&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonathanhayama/embed/JjpmeJV?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;No final do dia, com a lógica na cabeça, criei dois componentes, um baseado na quantidade de caracteres (sim, as vezes queremos limitar um texto por caracteres e não por linhas) e outro baseado em linhas.&lt;/p&gt;

&lt;p&gt;Agora, no nosso projeto sempre que precisamos disso basta utilizarmos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;line-clamp&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;"texto"&lt;/span&gt; &lt;span class="na"&gt;:lines=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;truncate-text&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;"texto"&lt;/span&gt; &lt;span class="na"&gt;:max-char=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span id="working-example"&gt;Exemplo:&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jonyhayama/embed/bGLQqzQ?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;IMPORTANTE:&lt;/strong&gt; Nenhum dos códigos acima foi compartilhado na intenção de ser copiado e colado, é apenas uma forma de exemplificar o recurso 😜&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Espero que isso lhe seja útil. Estou sempre aberto à pitacos e sugestões 😀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PS:&lt;/strong&gt; Confesso que adoraria uma solução que não dependesse de JS... juro que tentei...mas não encontrei... se souber, compartilha aí 🙏&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>vue</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Meu ambiente para desenvolvimento web com WSL2 - Apache + MySQL + PHP (WordPress)</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Mon, 08 Jun 2020 19:54:01 +0000</pubDate>
      <link>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-apache-mysql-php-wordpress-23of</link>
      <guid>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-apache-mysql-php-wordpress-23of</guid>
      <description>&lt;p&gt;Esse post é o último de uma série de 4&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-geral-3dag"&gt;Geral&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-ruby-on-rails-postgresql-1g8d"&gt;Ruby on Rails (PostgreSQL)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-javascript-adonisjs-react-vuejs-3h4a"&gt;Javascript (AdonisJS + React + VueJS)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-apache-mysql-php-wordpress-23of"&gt;Apache + MySQL + PHP (WordPress)&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Importante
&lt;/h3&gt;

&lt;p&gt;Quero reforçar que essa instalação é para um ambiente de &lt;strong&gt;DESENVOLVIMENTO&lt;/strong&gt;. Há diversas configurações de segurança que precisam ser feitas para um servidor de produção!&lt;/p&gt;

&lt;h3&gt;
  
  
  Apache
&lt;/h3&gt;

&lt;p&gt;Primeiramente vamos instalar o Apache. Para um ambiente PHP, há muitas pessoas que utilizam Nginx ou simplesmente o &lt;code&gt;php -S&lt;/code&gt;. Minha escolha pelo apache se dá por um motivo bastante simples: Tenho uma revenda de hospedagem com cPanel que utiliza essa tecnologia. Como coloco a vasta maioria dos meus clientes lá, prefiro que meu ambiente de desenvolvimento reflita (pelo menos em partes) o ambiente que terei por lá.&lt;/p&gt;

&lt;p&gt;Então bora:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update  
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para iniciar nosso servidor, basta utilizar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service apache2 start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acesse &lt;code&gt;http://localhost&lt;/code&gt; no seu navegador e verá a página padrão do apache2:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AuC0aDcicVRcb6-a9mYspBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AuC0aDcicVRcb6-a9mYspBA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  MySQL
&lt;/h3&gt;

&lt;p&gt;Como já está disponível no &lt;code&gt;apt&lt;/code&gt;, basta executar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;mysql-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim como na instalação do PostgreSQL, tenho o costume de criar um usuário para mim e não ficar utilizando o &lt;em&gt;root&lt;/em&gt; para tudo, portanto, vamos lá, acesse o &lt;em&gt;mysql&lt;/em&gt; com 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;&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Segue o comando para criar seu usuário:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="s1"&gt;'meu-nome-de-usuario'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'MinhaSenhaSecreta'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que ele está criado, precisamos dar permissão para que ele acesse todos os bancos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'meu-nome-de-usuario'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por fim, precisamos adicionar a permissão de conceder permissões para o nosso usuário:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;OPTION&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'meu-nome-de-usuario'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PHP
&lt;/h3&gt;

&lt;p&gt;A inslação do PHP em si é a mais direta possível:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;php libapache2-mod-php php-mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configurações adicionais
&lt;/h3&gt;

&lt;p&gt;Nem todas as configurações abaixo são necessárias para todos, por isso listá-las separadamente. A maioria delas exige que você reinicie o apache para que tenham efeito, portanto já vou deixar o comando aqui 😉&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service apache2 restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  PHPMyAdmin
&lt;/h4&gt;

&lt;p&gt;Há diversas formas de gerenciar seu banco de dados MySQL. Particularmente utilizo o PHPMyAdmin pelo mesmo motivo que uso o Apache: Para refletir meu ambiente de produção.&lt;/p&gt;

&lt;p&gt;Há quem prefira baixar os arquivos diretamente do &lt;a href="https://www.phpmyadmin.net/" rel="noopener noreferrer"&gt;site oficial&lt;/a&gt; e fazer as configurações manualmente. Pessoalmente prefiro instalá-lo pelo &lt;code&gt;apt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;phpmyadmin php-mbstring
&lt;span class="nb"&gt;sudo &lt;/span&gt;phpenmod mbstring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora precisamos adicionar as configurações que já vêm prontinhas ao apache, para isso vamos editar o arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/apache2/apache2.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basta adicionar essa linha ao final:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Include /etc/phpmyadmin/apache.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reinicie o apache e acesse &lt;code&gt;http://localhost/phpmyadmin&lt;/code&gt; para ver se tudo está funcionando :)&lt;/p&gt;

&lt;h4&gt;
  
  
  ModRewrite
&lt;/h4&gt;

&lt;p&gt;Como o WordPress utiliza o &lt;code&gt;mod_rewrite&lt;/code&gt; para criar suas URL amigáveis, é necessário ativá-lo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2enmod rewrite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Alterando a pasta padrão do Apache
&lt;/h4&gt;

&lt;p&gt;Pode ser frescura, mas prefiro ter meus projetos na pasta &lt;code&gt;~/www&lt;/code&gt;, “sue me”.&lt;/p&gt;

&lt;p&gt;Para que o apache considere essa pasta como o padrão para &lt;code&gt;localhost&lt;/code&gt;, precisamos editar o arquivo &lt;code&gt;000-default.conf&lt;/code&gt;. Particularmente estou usando o &lt;code&gt;vim&lt;/code&gt; como editor, mas você pode fazer com o editor de sua preferência:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/apache2/sites-enabled/000-default.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse arquivo, precisamos colocar o endereço completo de onde estão nossos arquivos. O atalho &lt;code&gt;~&lt;/code&gt; não funciona. Normalmente o endereço é &lt;code&gt;/home/meu-usuario/www&lt;/code&gt;. No meu caso, a pasta é &lt;code&gt;/home/jony/www&lt;/code&gt;. Se você não tem certeza de qual é o endereço da pasta que deseja, basta acessá-la e utilizar o comando &lt;code&gt;pwd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora que já sabemos o endereço que vamos utilizar, altere a linha do &lt;code&gt;DocumentRoot&lt;/code&gt; para o novo endereço e adicione o bloco abaixo no final do arquivo, lembre-se de substituir o meu endereço pelo seu 😉:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Directory "/home/jony/www"&amp;gt;  
   Order allow,deny  
   Allow from all  
   Options Indexes FollowSymLinks MultiViews  
   AllowOverride All  
   Require all granted  
&amp;lt;/Directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Permissão de arquivos
&lt;/h4&gt;

&lt;p&gt;Para que o apache consiga editar seus arquivos, você precisa que seus arquivos pertençam ao grupo &lt;code&gt;www-data&lt;/code&gt;, o problema é que nosso usuário não pertence a esse grupo, ou seja, se simplesmente trocarmos o grupo, nós perderíamos a possibilidade de editar nosso arquivos…&lt;/p&gt;

&lt;p&gt;Portanto, vamos adicionar nosso usuário ao grupo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;adduser &lt;span class="nv"&gt;$USER&lt;/span&gt; www-data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como eu compartilho a pasta &lt;code&gt;~/www&lt;/code&gt; entre vários projetos (nem todos PHP) prefiro adicionar permissões, projeto-a-projeto, portanto, toda vez que inicio um projeto php, rodo os seguintes comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt;:www-data /home/jony/www/novo-projeto  
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/www/novo-projeto
&lt;span class="nb"&gt;sudo &lt;/span&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;chmod &lt;/span&gt;664 &lt;span class="o"&gt;{}&lt;/span&gt; + &lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="nb"&gt;sudo &lt;/span&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; d &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;chmod &lt;/span&gt;775 &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;h4&gt;
  
  
  Permitindo arquivos maiores
&lt;/h4&gt;

&lt;p&gt;Por padrão, o tamanho máximo de upload de arquivos do apache é 2MB, que é bem pouco, portanto, vamos aumentá-lo. &lt;/p&gt;

&lt;p&gt;Para isso, vamos editar o arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/php/7.4/apache2/php.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Precisamos ajustar as duas configurações abaixo. Estou colocando 100M (representando 100 megabytes), mas você pode colocar outro valor que preferir.&lt;/p&gt;

&lt;p&gt;Infelizmente essas informações não estão perto uma da outra e o arquivo também é bem grande, portanto é necessário procurá-las.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;post_max_size = 100M  
upload_max_filesize = 100M
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dica:&lt;/strong&gt; Para fazer uma busca pelo &lt;code&gt;vim&lt;/code&gt; , basta digitar &lt;code&gt;/texto-procurado&lt;/code&gt; 😉&lt;/p&gt;

&lt;p&gt;Depois de alteradas, salve o arquivo e reinicie o apache.&lt;/p&gt;

&lt;h4&gt;
  
  
  SSL
&lt;/h4&gt;

&lt;p&gt;Muitas vezes instalo plugins no WordPress para fazer o redirecionamento para a versão com SSL do site. Em produção, com um servidor — de fato — certificado, funciona que é uma beleza, mas quando copio os arquivos para meu servidor local, fico trancado para fora do &lt;code&gt;/wp-admin&lt;/code&gt; 🤦‍♂️. Para facilitar a vida e não ter que ficar navegando no banco ou desativando o plugin toda vez que isso acontece, prefiro configurar um certificado auto-assinado localmente. Ainda vejo a mensagem de “site não seguro”, mas isso não é um problema, já que essa mensagem só aparece para mim :)&lt;/p&gt;

&lt;p&gt;Primeiro vamos habilitar o módulo no apache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2enmod ssl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reinicie seu apache e vamos criar o seguinte diretório:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /etc/apache2/ssl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos criar o certificado em si:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;openssl req &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="nt"&gt;-newkey&lt;/span&gt; rsa:2048 &lt;span class="nt"&gt;-keyout&lt;/span&gt; /etc/apache2/ssl/apache.key &lt;span class="nt"&gt;-out&lt;/span&gt; /etc/apache2/ssl/apache.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você precisará responder algumas perguntas para que o certificado seja gerado. Abaixo, deixei as respostas que utilizei:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Country Name (2 letter code) [AU]:BR  
State or Province Name (full name) [Some-State]:Minas Gerais  
Locality Name (eg, city) []:Varginha  
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Jony Hayama  
Organizational Unit Name (eg, section) []:&amp;lt;vazio&amp;gt;  
Common Name (e.g. server FQDN or YOUR name) []:localhost  
Email Address []:localhost@localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora precisamos configurar nosso apache para utilizar o certificado que criamos na pasta que desejamos, portanto vamos editar o arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/apache2/sites-available/default-ssl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Excluindo os comentários, esse arquivo vem com o conteúdo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;IfModule mod_ssl.c&amp;gt;
 &amp;lt;VirtualHost _default_:443&amp;gt;
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
  SSLEngine on
  SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
  SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
  &amp;lt;FilesMatch "\.(cgi|shtml|phtml|php)$"&amp;gt;
   SSLOptions +StdEnvVars
  &amp;lt;/FilesMatch&amp;gt;
  &amp;lt;Directory /usr/lib/cgi-bin&amp;gt;
   SSLOptions +StdEnvVars
  &amp;lt;/Directory&amp;gt;
 &amp;lt;/VirtualHost&amp;gt;
&amp;lt;/IfModule&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O arquivo finalizado ficará assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;IfModule mod_ssl.c&amp;gt;
 &amp;lt;VirtualHost _default_:443&amp;gt;
  ServerAdmin webmaster@localhost
  ServerName localhost
  DocumentRoot /home/jony/www
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
  SSLEngine on
  SSLCertificateFile /etc/apache2/ssl/apache.crt
  SSLCertificateKeyFile /etc/apache2/ssl/apache.key
  &amp;lt;FilesMatch "\.(cgi|shtml|phtml|php)$"&amp;gt;
   SSLOptions +StdEnvVars
  &amp;lt;/FilesMatch&amp;gt;
  &amp;lt;Directory /home/jony/www&amp;gt;
   SSLOptions +StdEnvVars
   DirectoryIndex index.php
   AllowOverride All
   Order allow,deny
   Allow from all
  &amp;lt;/Directory&amp;gt;
  BrowserMatch "MSIE [2-6]" \
          nokeepalive ssl-unclean-shutdown \
          downgrade-1.0 force-response-1.0
  BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
 &amp;lt;/VirtualHost&amp;gt;
&amp;lt;/IfModule&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Destaquei o endereço pois eu não utilizo o endereço padrão do apache que é &lt;code&gt;/var/www/html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por fim, é necessário habilitar as configurações do arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2ensite default-ssl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prontinho, basta reiniciar seu apache e você poderá acessar &lt;code&gt;http**s**://localhost&lt;/code&gt; .&lt;/p&gt;

&lt;h3&gt;
  
  
  WordPress
&lt;/h3&gt;

&lt;p&gt;Instalar o WordPress também é simples e direto, então bora lá:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="o"&gt;[&lt;/span&gt;https://wordpress.org/latest.tar.gz]&lt;span class="o"&gt;(&lt;/span&gt;https://wordpress.org/latest.tar.gz&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-vzxf&lt;/span&gt; latest.tar.gz&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;mv &lt;/span&gt;wordpress &lt;span class="k"&gt;**&lt;/span&gt;nova-pasta&lt;span class="k"&gt;**&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lembre-se de ajustar as permissões de arquivo conforme descrito mais acima.&lt;/p&gt;

&lt;p&gt;Agora basta acessar &lt;code&gt;http://localhost/**nova-pasta**&lt;/code&gt; e seguir os passos de instalação do próprio WP.&lt;/p&gt;

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

&lt;p&gt;Este ambiente não é perfeito, mas têm me atendido bem. Em linhas gerais gostaria que o WSL tivesse um pouco mais de performance, mas nada que atrapalhe o dia-a-dia. &lt;/p&gt;

&lt;p&gt;Basicamente acredito que o WSL é um ótimo meio termo entre Linux direto e um Mac. Se você, como eu, precisa de diversos aplicativos comerciais que não estão disponíveis para o pinguim e não tem grana suficiente para comprar uma maçã, acredito que esse ambiente é para você :)&lt;/p&gt;

&lt;p&gt;Essa foi a minha primeira série de posts publicada no Medium, espero que tenha gostado!&lt;/p&gt;

</description>
      <category>wsl2</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>Meu ambiente para desenvolvimento web com WSL2 - Javascript (AdonisJS + React + VueJS)</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Tue, 02 Jun 2020 12:24:46 +0000</pubDate>
      <link>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-javascript-adonisjs-react-vuejs-3h4a</link>
      <guid>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-javascript-adonisjs-react-vuejs-3h4a</guid>
      <description>&lt;p&gt;Esse post é o terceiro de uma série de 4&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-geral-3dag"&gt;Geral&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-ruby-on-rails-postgresql-1g8d"&gt;Ruby on Rails (PostgreSQL)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-javascript-adonisjs-react-vuejs-3h4a"&gt;Javascript (AdonisJS + React + VueJS)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-apache-mysql-php-wordpress-23of"&gt;Apache + MySQL + PHP (WordPress)&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Como banco de dados para o AdonisJS, utilizo o PostgreSQL, que já mostrei como faço a instalação no post anterior, portanto não vou repeti-lo :)&lt;/p&gt;

&lt;p&gt;O fato mais interessante do WSL é que ele permite que executemos comandos na Distro (quase) como se estivéssemos rodando o Linux diretamente. Há alguns detalhes aqui e ali, mas confesso que fiquei bastante surpreso com o fato da instalação do Node ser exatamente igual à que fazia diretamente no Ubuntu.&lt;/p&gt;

&lt;h3&gt;
  
  
  NVM
&lt;/h3&gt;

&lt;p&gt;Esse é o gerenciador de versões do Node, da mesma forma que o RVM é para o Ruby.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o-&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh]&lt;span class="o"&gt;(&lt;/span&gt;https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh&lt;span class="o"&gt;)&lt;/span&gt; | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;IMPORTANTE:&lt;/strong&gt; durante a escrita desse post, a última versão disponível era a &lt;code&gt;0.35.3&lt;/code&gt;, recomendo que dê uma olhada no repositório oficial para instalar a versão mais recente: &lt;a href="https://github.com/nvm-sh/nvm#install--update-script"&gt;https://github.com/nvm-sh/nvm#install--update-script&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Durante a instalação o NVM faz o seu melhor para já se adicionar ao arquivo &lt;code&gt;~/.zshrc&lt;/code&gt;, mas ele nem sempre consegue 🤷‍♀️. Portanto, abra uma nova aba e verifique se é possível executar o comando &lt;code&gt;nvm -v&lt;/code&gt; (se você vêm seguindo desde o começo, pode só verificar se o termo &lt;code&gt;nvm&lt;/code&gt; fica verde 😉).&lt;/p&gt;

&lt;p&gt;Caso o NVM não esteja disponível, não se desespere, basta adicionar as linhas abaixo ao final do seu arquivo &lt;code&gt;~./zshrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NVM_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.nvm"&lt;/span&gt;  
&lt;span class="se"&gt;\[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM&lt;/span&gt;&lt;span class="se"&gt;\_&lt;/span&gt;&lt;span class="s2"&gt;DIR/nvm.sh"&lt;/span&gt; &lt;span class="se"&gt;\]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM&lt;/span&gt;&lt;span class="se"&gt;\_&lt;/span&gt;&lt;span class="s2"&gt;DIR/nvm.sh"&lt;/span&gt; &lt;span class="c"&gt;# This loads nvm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Node e NPM
&lt;/h4&gt;

&lt;p&gt;Depois de instalado o NVM, é hora de instalar o Node. Particularmente sempre instalo a versão LTS primeiro para deixá-la como padrão, portanto aí vai o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--lts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Yarn
&lt;/h3&gt;

&lt;p&gt;Via de regra prefiro usar o Yarn como gerenciador de dependências. Em linhas gerais eu o considero mais performático e, como estamos num ambiente que é — por definição — mais lento do que se estivéssemos diretamente no Linux, qualquer milésimo de segundo conta!&lt;/p&gt;

&lt;p&gt;Primeiro precisamos adicionar o yarn ao repositório apt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://dl.yarnpkg.com/debian/pubkey.gpg]&lt;span class="o"&gt;(&lt;/span&gt;https://dl.yarnpkg.com/debian/pubkey.gpg&lt;span class="o"&gt;)&lt;/span&gt; | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -  
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [https://dl.yarnpkg.com/debian/](https://dl.yarnpkg.com/debian/) stable main"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/yarn.list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora é só rodar&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se tudo ocorreu bem, você deve conseguir rodar &lt;code&gt;yarn -v&lt;/code&gt; e ver a versão instalada.&lt;/p&gt;

&lt;p&gt;Além disso, para conseguirmos instalar pacotes globalmente, precisamos adicionar a linha abaixo no nosso &lt;code&gt;~/.zshrc&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;yarn global bin&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso tenha dúvidas, basta dar um pulinho da documentação oficial: &lt;a href="https://classic.yarnpkg.com/en/docs/install/#debian-stable"&gt;https://classic.yarnpkg.com/en/docs/install/#debian-stable&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como diria o ditado, estamos com a faca e o queijo na mão. Agora que o ambiente está pronto, podemos seguir com nosso desenvolvimento JS normalmente. Abaixo vou listar os comandos para instalação dos CLIs de cada biblioteca/framework que utilizo e como verificar sua instalação.&lt;/p&gt;

&lt;h3&gt;
  
  
  AdonisJS
&lt;/h3&gt;

&lt;p&gt;Instale com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn global add &lt;span class="o"&gt;[&lt;/span&gt;@adonisjs/cli]&lt;span class="o"&gt;(&lt;/span&gt;http://twitter.com/adonisjs/cli &lt;span class="s2"&gt;"Twitter profile for @adonisjs/cli"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verifique com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adonis &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documentação: &lt;a href="https://adonisjs.com/docs/4.1/installation"&gt;https://adonisjs.com/docs/4.1/installation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;Instale com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn global add create-react-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verifique com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;create-react-app &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documentação: &lt;a href="https://create-react-app.dev/docs/getting-started/"&gt;https://create-react-app.dev/docs/getting-started/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Vue
&lt;/h3&gt;

&lt;p&gt;Instale com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn global add &lt;span class="o"&gt;[&lt;/span&gt;@vue/cli]&lt;span class="o"&gt;(&lt;/span&gt;http://twitter.com/vue/cli &lt;span class="s2"&gt;"Twitter profile for @vue/cli"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verifique com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vue &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documentação: &lt;a href="https://cli.vuejs.org/guide/installation.html"&gt;https://cli.vuejs.org/guide/installation.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wsl2</category>
      <category>node</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Meu ambiente para desenvolvimento web com WSL2 - Ruby on Rails (PostgreSQL)</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Mon, 25 May 2020 17:34:07 +0000</pubDate>
      <link>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-ruby-on-rails-postgresql-1g8d</link>
      <guid>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-ruby-on-rails-postgresql-1g8d</guid>
      <description>&lt;p&gt;Esse post é o segundo de uma série de 4&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-geral-3dag"&gt;Geral&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-ruby-on-rails-postgresql-1g8d"&gt;Ruby on Rails (PostgreSQL)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-javascript-adonisjs-react-vuejs-3h4a"&gt;Javascript (AdonisJS + React + VueJS)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-apache-mysql-php-wordpress-23of"&gt;Apache + MySQL + PHP (WordPress)&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Na empresa onde trabalho, utilizamos Ruby on Rails com PostgreSQL para quase todos os projetos, é a nossa “&lt;em&gt;go to language&lt;/em&gt;”. &lt;/p&gt;

&lt;h3&gt;
  
  
  PostgreSQL
&lt;/h3&gt;

&lt;p&gt;Antes de mais nada, gosto de instalar o banco de dados. Estranhamente (ou não), durante a escrita deste post encontrei um erro ao fazer a instalação do banco que (até hoje) não consegui descobrir o motivo exato. &lt;/p&gt;

&lt;p&gt;Depois de instalado tudo parece ok, entretanto, não é possível conectar-se ao banco. Sempre ocorre o erro de que o servidor não foi iniciado. Tentei fazer diversos ajustes no &lt;code&gt;postgresql.conf&lt;/code&gt; e no &lt;code&gt;pg_hba.conf&lt;/code&gt;, mas o fato é que há algum problema na instalação do PostgreSQL no WSL2. É necessário, portanto, reverter ao WSL1 para fazer a instalação. Ao final, pode voltar ao WSL2 que tudo funcionará perfeitamente.&lt;/p&gt;

&lt;p&gt;Caso não se lembre, o comando a ser executado no PowerShell é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--set-version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Distro&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Version&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, abra seu WSL e rode 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;sudo &lt;/span&gt;apt update  
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;postgresql postgresql-contrib libpq-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Via de regra, sempre crio um usuário de banco “superuser” com o mesmo nome do meu usuário Linux. Para isso, basta mudarmos para a conta postgres:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e usar o comando abaixo para criar o usuário:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;createuser &lt;span class="nt"&gt;--interactive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O próprio script irá te solicitar que preencha os dados do novo usuário. Como disse antes, sempre crio um usuário que possui o mesmo nome do meu usuário linux. Caso não seja solicitada a senha durante a criação do usuário, pasta acessar o &lt;code&gt;psql&lt;/code&gt; e executar o comando abaixo substituindo &lt;code&gt;[nome-do-usuario]&lt;/code&gt; pelo nome de usuário que você acabou de criar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\password [nome-do-usuario]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se foi necessário criar uma senha utilizando o comando acima, digite &lt;code&gt;\q&lt;/code&gt; para sair do &lt;code&gt;psql&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Depois de criado o nosso usuário, já não há mais necessidade de estar logado com a conta postgres, portanto pode sair utilizando o comando &lt;code&gt;exit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por força do hábito, sempre que preciso criar um banco, utilizo 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;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres createdb &lt;span class="o"&gt;[&lt;/span&gt;nome-do-banco]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Há, naturalmente, diversas formas mais práticas de criar e gerenciar seus bancos de dados do que o terminal. Minha sugestão é instalar o &lt;a href="https://www.pgadmin.org/" rel="noopener noreferrer"&gt;pgAdmin&lt;/a&gt;. É só baixar a versão para Windows e configurar o acesso como &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Uma característica do WSL é que é necessário iniciar o servidor sempre que o WSL for fechado, portanto segue o comando:&lt;/p&gt;

&lt;p&gt;sudo service postgresql start&lt;/p&gt;

&lt;h3&gt;
  
  
  RVM
&lt;/h3&gt;

&lt;p&gt;Para gerenciar as versões do Ruby, utilizo o RVM. Há uma versão dedicada ao Ubuntu e para instalá-la, precisamos, primeiramente instalar o &lt;code&gt;software-properties-common&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;software-properties-common
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, precisamos adicionar o PPA e instalá-lo via &lt;code&gt;apt&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-add-repository &lt;span class="nt"&gt;-y&lt;/span&gt; ppa:rael-gc/rvmsudo apt-get updatesudo apt-get &lt;span class="nb"&gt;install &lt;/span&gt;rvm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por fim, para que o RVM venha sempre carregado, precisamos 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;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'source "/etc/profile.d/rvm.sh"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse último é um pouco diferente da documentação oficial, pois utilizamos o &lt;code&gt;zsh&lt;/code&gt; e não o &lt;code&gt;bash&lt;/code&gt;. Caso encontre algum problema, acesse o repositório oficial: &lt;a href="https://github.com/rvm/ubuntu_rvm" rel="noopener noreferrer"&gt;https://github.com/rvm/ubuntu_rvm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora você já pode rodar o comando abaixo para instalar a versão do Ruby que seu projeto utiliza:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rvm &lt;span class="nb"&gt;install &lt;/span&gt;ruby[-versao-do-ruby]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso seja uma aplicação novinha em folha, basta omitir a versão e instalar a mais recente :)&lt;/p&gt;

&lt;p&gt;Agora que temos o Ruby instalado, precisamos também instalar o bundler&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Letter Opener
&lt;/h4&gt;

&lt;p&gt;Se você, como eu, utiliza a gem &lt;code&gt;letter_opener&lt;/code&gt;, você perceberá que o navegador não abre quando o e-mail é enviado. Isso pois o comando para abrir o navegador é enviado para seu WSL, portanto é necessário fazer uma configuração adicional para que o WSL encontrei seu browser. No meu caso, utilizo o Chrome, portanto, basta adicionar a seguinte linha ao seu &lt;code&gt;~/.zshrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Add BROWSER  
export BROWSER='/mnt/c/Program\ Files\ \\(x86\\)/Google/Chrome/Application/chrome.exe'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outro probleminha que encontrará é que, agora, seu navegador abre, mas o endereço do arquivo é incorreto&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AlB0voZbI0WhWU5MuqmTc0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AlB0voZbI0WhWU5MuqmTc0w.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ainda não descobri uma forma de fazer isso automaticamente, por hora eu simplesmente adiciono o endereço abaixo ao caminho gerado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wsl%24/Ubuntu-20.04/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;o caminho acaba ficando algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file://wsl%24/Ubuntu-20.04/home/jony/www/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NodeJS
&lt;/h3&gt;

&lt;p&gt;Por fim, as versões mais recentes do Rails precisam do Node para funcionar. Em especial por terem substituído o Sprockets pelo Webpacker. Como eu utilizo o mesmo ambiente para desenvolver aplicações JS eu prefiro usar o NVM (que vou explicar como instalar na próxima postagem da série), mas nada impede que você instale a versão do node disponível no &lt;code&gt;apt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nodejs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir daqui já podemos seguir com um fluxo trabalho comum... Podemos executar &lt;code&gt;bundle install&lt;/code&gt;, &lt;code&gt;rails db:migration&lt;/code&gt;, &lt;code&gt;rails s&lt;/code&gt;, etc... &lt;/p&gt;

&lt;p&gt;Como o objetivo desse post é compartilhar meu ambiente de trabalho, vou parando por aqui, mas se tiver interesse em “continuar nesse caminho”, dê uma olhada no Guia oficial: &lt;a href="https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application" rel="noopener noreferrer"&gt;https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>wsl2</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Meu ambiente para desenvolvimento web com WSL2 - Geral</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Mon, 18 May 2020 17:02:25 +0000</pubDate>
      <link>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-geral-3dag</link>
      <guid>https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-geral-3dag</guid>
      <description>&lt;p&gt;Há mais ou menos seis meses tenho utilizado o WSL2 como meu ambiente principal de desenvolvimento. Anteriormente usava a versão 1 e anteriormente o Ubuntu.&lt;/p&gt;

&lt;p&gt;Atualmente tenho diferentes projetos criados com Ruby on Rails, React, AdonisJS, VueJS, WordPress e utilizo o VS Code como editor principal.&lt;/p&gt;

&lt;p&gt;Esse é o primeiro post de uma série de 4:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-geral-3dag"&gt;Geral&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-ruby-on-rails-postgresql-1g8d"&gt;Ruby on Rails (PostgreSQL)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-javascript-adonisjs-react-vuejs-3h4a"&gt;Javascript (AdonisJS + React + VueJS)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://dev.to/jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-apache-mysql-php-wordpress-23of"&gt;Apache + MySQL + PHP (WordPress)&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Muitos usuário Linux vão torcer o nariz e dizer que seria melhor utilizar o Ubuntu diretamente ou o Mint ou Debian ou qualquer outra distro. Em linhas gerais, concordo. Meu principal problema, entretanto, é o simples fato dos aplicativos comerciais (como Photoshop, CorelDraw, Illustrator, pacote Office, etc.) não serem muito amigáveis com o pinguim. &lt;/p&gt;

&lt;p&gt;Já usei as alterativas open source (como Gimp, Inkscape, LibreOffice, etc.), mas não consigo obrigar parceiros de trabalho a fazer o mesmo 🤷‍♂️. Já usei Wine, mas no final ficou meio "esquisito". Já usei dual boot e não suporto ter que reiniciar a máquina só por conta de uma aplicação.&lt;/p&gt;

&lt;p&gt;Como (ainda) não tenho condições de trocar meu carro por uma maçã mordida, fico com o Windows que já veio instalado no meu notebook.&lt;/p&gt;

&lt;p&gt;WSL não é perfeito. A versão 1 é bem lenta quando se trata de trabalho com muitos arquivos (leia-se &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;bundle install&lt;/code&gt; e similares). A versão 2 trás uma melhora significativa nesse aspecto (apesar de ter seus problemas também). A Microsoft têm trabalhado bastante nessa frente e eu acredito que o resultado é excepcional. Vale lembrar, entretanto, que ainda estamos na fase de "preview", ou seja, alguns bugs são esperados.&lt;/p&gt;

&lt;p&gt;Enfim, a ideia deste post não é justificar cada uma das minha escolhas, mas apenas compartilhá-las :)&lt;/p&gt;

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

&lt;p&gt;Antes de mais nada é necessário habilitar o WSL no sistema. Para isso,  basta executar o comando abaixo no PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Enable-WindowsOptionalFeature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Online&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FeatureName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Microsoft-Windows-Subsystem-Linux&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim que o comando terminar de executar, será solicitado que você reinicie seu PC.&lt;/p&gt;

&lt;p&gt;Agora, vá na Microsoft Store e faça uma busca por "Ubuntu". Existem outras distros na loja, não cheguei a testá-las, mas como já estou acostumado, uso o Ubuntu mesmo. A versão que utilizo é a 18.04.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xT0xeJpnrWC4XWblEk/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xT0xeJpnrWC4XWblEk/giphy.gif" alt="Mind Blow" width="350" height="233"&gt;&lt;/a&gt;&lt;/p&gt;
Pausa para assimilar a instalação de uma distro Linux dentro da Microsoft Store…



&lt;p&gt;Clique em "Obter" e a própria Store fará a instalação. Depois de instalado, será possível acessar o ambiente do Ubuntu diretamente do menu Iniciar. Na primeira vez que você o fizer, será necessário cadastrar seu usuário senha.&lt;/p&gt;

&lt;p&gt;Já fiz esse setup diversas vezes para diversos colegas de trabalho e até hoje não tive problemas, mas a própria Microsoft possui um Troubleshoot nesse link: &lt;a href="https://docs.microsoft.com/pt-br/windows/wsl/install-win10"&gt;https://docs.microsoft.com/pt-br/windows/wsl/install-win10&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ativando a versão 2
&lt;/h3&gt;

&lt;p&gt;Para usar a versão do WLS, é necessário (até o momento de escrita dessa postagem) ingressar no &lt;a href="https://insider.windows.com/en-us/"&gt;Windows Insider Program&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Agora, é necessário ativar o componente opcional "Plataforma de máquina virutal", o que pode ser feito executando os comandos abaixo no PowerShell e reiniciando o PC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dism.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/online&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/enable-feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/featurename:Microsoft-Windows-Subsystem-Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/norestart&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;dism.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/online&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/enable-feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/featurename:VirtualMachinePlatform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/norestart&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De volta ao PowerShell, você pode verificar a versão do WSL para cada versão usando o comando &lt;code&gt;wsl -l -v&lt;/code&gt;. Agora é só executar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--set-version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Distro&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso precise de mais detalhes, acesse a documentação da própria Microsoft: &lt;a href="https://docs.microsoft.com/pt-br/windows/wsl/wsl2-install"&gt;https://docs.microsoft.com/pt-br/windows/wsl/wsl2-install&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows Terminal
&lt;/h2&gt;

&lt;p&gt;Existem várias opções para usar um terminal no Windows. Uma das mais populares é o Hyper, que funciona muito bem também, mas com o &lt;a href="https://www.microsoft.com/pt-br/p/windows-terminal-preview/9n0dx20hk701?activetab=pivot:overviewtab"&gt;Windows Terminal&lt;/a&gt; foi amor à primeira vista. Nele você consegue abrir abas de qualquer terminal que existe no Windows (Power Shell, cmd, WSL), ele aceita splits e a configuração é um simples JSON!&lt;/p&gt;

&lt;p&gt;Então corre lá na Microsoft Store e instale-o, pode me agradecer depois ;)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://ohmyz.sh/"&gt;Oh my ZSH&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Particularmente gosto de um terminal cheio de auxílios visuais. Algo nessa linha:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--evmDJ8ul--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jyoagrt12efybxfne2xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--evmDJ8ul--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jyoagrt12efybxfne2xe.png" alt="Windows Terminal" width="880" height="501"&gt;&lt;/a&gt;&lt;/p&gt;
Terminal sexy



&lt;p&gt;Para chegar lá, primeiro precisamos instalar o ZSH:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;zsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que o ZSH está instalado, bora instalar o Oh My ZSH&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Existem diversos plugins com diversas funcionalidades que já vêm junto com a instalação, você pode ver a lista completa em &lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins"&gt;https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Particularmente uso dois que não estão na lista:&lt;/p&gt;

&lt;p&gt;1 - &lt;a href="https://github.com/zsh-users/zsh-syntax-highlighting"&gt;zsh-syntax-highlighting&lt;/a&gt; que adiciona uma cor verde ou vermelha ao digitar um comando para te ajudar a ver se está correto ou não, para instalá-lo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-syntax-highlighting.git &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/plugins/zsh-syntax-highlighting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 - &lt;a href="https://github.com/zsh-users/zsh-autosuggestions"&gt;zsh-autosuggestions&lt;/a&gt; que irá exibir sugestões de comandos baseado no histórico de comandos que você já digitou, para instalá-lo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions &lt;span class="nv"&gt;$ZSH_CUSTOM&lt;/span&gt;/plugins/zsh-autosuggestions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois de instalar os plugins será necessários adicioná-los na linha de plugins no seu &lt;code&gt;~./zshrc&lt;/code&gt;, vai ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins=(
 git
 zsh-syntax-highlighting
 zsh-autosuggestions
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/romkatv/powerlevel10k#oh-my-zsh"&gt;Powerlevel10k&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Esse será o responsável por deixar nosso terminal bonitão! Para exibir os ícones da maneira correta, primeiro precisamos instalar uma Nerd Font. Via de regra eu uso a Hack, mas se você é daqueles programadores que curte uma "ligature" sugiro a FiraCode. Baixe o pacode &lt;code&gt;zip&lt;/code&gt; e instale as fontes.&lt;/p&gt;

&lt;p&gt;Agora só é necessário ajustar a configuração do nosso terminal para exibir essa nova fonte. Já que vamos alterar esse arquivo, acredito que seja uma boa oportunidade para instalar o tema Dracula (que eu adoro).&lt;/p&gt;

&lt;p&gt;Então abra as opções do seu terminal (&lt;code&gt;ctrl + ,&lt;/code&gt;) e adicione o array abaixo, logo depois do array de &lt;code&gt;profiles&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"schemes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dracula"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"background"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#272935"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"black"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#21222C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"blue"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#BD93F9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"cyan"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#8BE9FD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"foreground"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#F8F8F2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"green"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#50FA7B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"purple"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FF79C6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"red"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FF5555"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"white"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#F8F8F2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"yellow"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FFB86C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightBlack"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#6272A4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightBlue"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#D6ACFF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightCyan"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#A4FFFF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightGreen"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#69FF94"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightPurple"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FF92DF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightRed"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FF6E6E"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightWhite"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#F8F8F2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"brightYellow"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FFFFA5"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, no seu array de &lt;code&gt;profiles&lt;/code&gt; altere o objeto do seu WSL acrescentando o seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"fontFace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FiraCode Nerd Font"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"colorScheme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dracula"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"fontSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seu objeto ficará mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"guid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ubuntu-20.04"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Windows.Terminal.Wsl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fontFace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FiraCode Nerd Font"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"colorScheme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dracula"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fontSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ainda nas opções do terminal, sugiro alterar o &lt;code&gt;defaultProfile&lt;/code&gt; para o &lt;code&gt;guid&lt;/code&gt; equivalente ao seu WSL, assim eles será o padrão ao abrir uma nova aba.&lt;/p&gt;

&lt;p&gt;Finalmente é hora de instalar o Powerlevel10k, portanto execute esse comando no seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 https://github.com/romkatv/powerlevel10k.git &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/themes/powerlevel10k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora abra seu &lt;code&gt;~/.zshrc&lt;/code&gt; e altere a linha do tema para &lt;code&gt;ZSH_THEME="powerlevel10k/powerlevel10k"&lt;/code&gt; e abra uma nova aba do WLS. Você será levado para um wizard para que escolha as opções que achar mais interessante.&lt;/p&gt;

&lt;h2&gt;
  
  
  VS Code
&lt;/h2&gt;

&lt;p&gt;Acesse o site e baixe o instalável: &lt;a href="https://code.visualstudio.com/"&gt;https://code.visualstudio.com/&lt;/a&gt;. A instalação segue o bom e velho modelo "next, next, next, install". Sim, a instalação é feita no Windows e não no WSL.&lt;/p&gt;

&lt;p&gt;Para fazer com que ele funcione em conjunto com o WSL, é necessário adicionar duas extensões, aí vão:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack"&gt;Remote Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl"&gt;Remote - WSL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depois das extensões instaladas, basta acessar uma pasta no seu WSL e executar &lt;code&gt;code .&lt;/code&gt; e o VS Code baixará um server para seu WSL e abrirá com a indicação de que você está no seu ambiente Ubuntu. &lt;/p&gt;

&lt;p&gt;Como já disse, adoro o tema Drácula, e alguns auxílios visuais, portanto vou deixar aqui uma pequena lista das extensões que uso no meu dia-a-dia bem como algumas configurações que utilizo no meu editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extensões:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer"&gt;Bracket Pair Colorizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dracula-theme.theme-dracula"&gt;Dracula Official&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vincaslt.highlight-matching-tag"&gt;Highlight Matching Tag&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=PKief.material-icon-theme"&gt;Material Icon Theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens"&gt;GitLens&lt;/a&gt; (não só pelos auxílios visuais, mas adoro o current line blame 😂)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;settings.json&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"editor.tabSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"highlight-matching-tag.styles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"opening"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"full"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"custom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"dark"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rgba(255, 255, 255, .15)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1px 0 1px 0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rgb(80, 250, 123)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10px"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"light"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rgba(0, 0, 0, .15)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1px 0 1px 0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"brown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10px"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"closing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"full"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"custom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"dark"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rgba(255, 255, 255, .15)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1px 0 1px 0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rgb(80, 250, 123)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10px"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"light"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rgba(0, 0, 0, .15)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1px 0 1px 0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"brown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"borderStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10px"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"files.autoSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"editor.fontFamily"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'FiraCode Nerd Font', Consolas, 'Courier New', monospace"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"editor.fontLigatures"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'ss01', 'ss02', 'ss03', 'ss05'"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acredito que essas configurações sejam bem genéricas e se aplicam a qualquer linguagem que você resolva utilizar para desenvolver. Como disse no começo dessa postagem, eu utilizo stacks diferentes dependendo do projeto em que vou trabalhar. Nas próximas postagens vou compartilhar stack por stack, acompanhe! 😊&lt;/p&gt;

&lt;p&gt;Também publicado no &lt;a href="https://medium.com/@jonyhayama/meu-ambiente-para-desenvolvimento-web-com-wsl2-geral-4a206b3194be"&gt;Medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ubuntu</category>
      <category>wsl2</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Como clonar um app no Heroku</title>
      <dc:creator>Jony Hayama</dc:creator>
      <pubDate>Sun, 17 May 2020 19:48:35 +0000</pubDate>
      <link>https://dev.to/jonyhayama/como-clonar-um-app-no-heroku-3mao</link>
      <guid>https://dev.to/jonyhayama/como-clonar-um-app-no-heroku-3mao</guid>
      <description>&lt;p&gt;Originalmente postado no &lt;a href="https://medium.com/@jonyhayama/como-clonar-um-app-no-heroku-f8b7488950e3"&gt;Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hoje fui confrontado com uma task super simples: Criar 3 ambientes de &lt;em&gt;staging&lt;/em&gt; para que nossos QAs trabalharem e assim evitar que fiquem “trombando” uns nos outros. O nosso cenário até o momento era, 1 ambiente por projeto e 2 profissionais para fazer os testes.&lt;/p&gt;

&lt;p&gt;Nosso problema surgiu quando decidimos fazer uma força-tarefa e agilizar as entregas para um cliente em específico. Todo o time será realocado para o mesmo projeto. Aliado a isso, um novo QA foi contratado para compor a equipe.&lt;/p&gt;

&lt;p&gt;Agora ficamos: 1 projeto, 3 QAs e apenas 1 ambiente para que façam seus testes.&lt;/p&gt;

&lt;p&gt;Com apenas um ambiente, é natural que não consigam testar coisas diferentes em paralelo. Nossa ideia foi bastante simples: Criar um ambiente de staging para cada um e compartilho como fizemos:&lt;/p&gt;

&lt;p&gt;A ideia é copiar o app &lt;code&gt;my-staging&lt;/code&gt; para &lt;code&gt;my-new-staging&lt;/code&gt;. Estou partindo do pressuposto que o &lt;a href="https://devcenter.heroku.com/articles/heroku-cli"&gt;Heroku Cli&lt;/a&gt; já está instalado e operando.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repositório
&lt;/h2&gt;

&lt;p&gt;Aqui trabalhamos com o Automatic Deploy, vinculado a uma branch específica do GitHub (carinhosamente chamada de &lt;code&gt;stg/star-wars&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Esse processo é bastante simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout master
git pull
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; stg/star-wars
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois crie a nova aplicação no Heroku e na seção “Deploy” conecte seu GitHub e escolha a branch conforme o print abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WXkF0Cza--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v8uha9c449e8mwwlmkgr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WXkF0Cza--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v8uha9c449e8mwwlmkgr.png" alt="Heroku Config" width="700" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Copiando as variáveis de ambiente
&lt;/h2&gt;

&lt;p&gt;Primeiro copiamos as variáveis para um &lt;code&gt;txt&lt;/code&gt; qualquer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku config &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; my-staging &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; heroku-env.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois é necessário enviá-las para a nova aplicação. Antes disso, é importante revisar as variáveis que, de fato, precisam ir. De cara, precisamos remover &lt;code&gt;DATABASE_URL&lt;/code&gt;, já que o banco de dados será outro.&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;cat &lt;/span&gt;heroku-env.txt | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; | xargs heroku config:set &lt;span class="nt"&gt;-a&lt;/span&gt; my-new-staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Copiando o banco de dados (PostgreSQL)
&lt;/h2&gt;

&lt;p&gt;Primeiramente precisamos gerar o backup na app de origem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku pg:backups:capture &lt;span class="nt"&gt;-a&lt;/span&gt; my-staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comando terá uma resposta parecida com o print abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QjPdKi08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dr071jp0p5skh41tbjfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QjPdKi08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dr071jp0p5skh41tbjfm.png" alt="Heroku DB Response" width="700" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O importante aqui é a referência &lt;code&gt;b079&lt;/code&gt;, que utilizaremos no próximo comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku pg:backups:restore my-staging::b079 &lt;span class="nt"&gt;--app&lt;/span&gt; my-new-staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeti esse processo mais duas vezes e &lt;em&gt;voilà&lt;/em&gt; card movido para “done” 😃&lt;/p&gt;

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