<?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: Luiz Fernando Puri</title>
    <description>The latest articles on DEV Community by Luiz Fernando Puri (@fernandopuri_dev).</description>
    <link>https://dev.to/fernandopuri_dev</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%2F2259711%2F3bb5ca01-d246-412a-8a19-659431f5db61.png</url>
      <title>DEV Community: Luiz Fernando Puri</title>
      <link>https://dev.to/fernandopuri_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fernandopuri_dev"/>
    <language>en</language>
    <item>
      <title>Code Agents: Como aumentar a produtividade sem se tornar dependente</title>
      <dc:creator>Luiz Fernando Puri</dc:creator>
      <pubDate>Thu, 12 Feb 2026 17:00:04 +0000</pubDate>
      <link>https://dev.to/fernandopuri_dev/code-agents-como-aumentar-a-produtividade-sem-se-tornar-dependente-2hp3</link>
      <guid>https://dev.to/fernandopuri_dev/code-agents-como-aumentar-a-produtividade-sem-se-tornar-dependente-2hp3</guid>
      <description>&lt;p&gt;Há alguns meses, comecei a usar Code Agents para acelerar meu fluxo de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Codex, Claude Code, Gemini CLI, Copilot&lt;/p&gt;

&lt;p&gt;De primeiro momento, assim como muitos Devs, eu tinha um pouco de medo. Uma tecnologia nova que me fazia ter medo de ser substituído. &lt;/p&gt;

&lt;p&gt;Depois fiquei impressionado com o aumento de produtividade que comecei a ter. Tarefas que talvez levariam semanas, resolvidas em poucos dias. &lt;/p&gt;

&lt;p&gt;Também senti um alívio ao perceber que no fim das contas, ainda era eu quem tornava o desenvolvimento possível.&lt;/p&gt;

&lt;p&gt;Mesmo com prompts bem estruturados, eu precisava pensar na engenharia, revisar decisões e corrigir erros ou alucinações.&lt;/p&gt;

&lt;p&gt;Porém em determinado momento percebi que me acostumei com o uso dessas ferramentas, surgiu um novo medo, o medo de esquecer as bases e ficar dependente. &lt;/p&gt;

&lt;p&gt;De perder a capacidade de conseguir fazer sozinho, já que a IA fazia boa parte do trabalho bruto.&lt;/p&gt;

&lt;p&gt;Caso eu precisasse fazer algum desafio técnico, e criar um sistema do zero sem uso de code agent nenhum, eu teria mais dificuldades?&lt;/p&gt;

&lt;p&gt;Provavelmente sim. Assim como quando voltamos de férias e nos sentimos um pouco enferrujados no desenvolvimento, a prática constante faz diferença.&lt;/p&gt;

&lt;p&gt;Foi então que comecei a pensar em formas mais saudáveis de usar essas ferramentas: manter a produtividade sem perder a base técnica — e, melhor ainda, usá-las como aliadas no aprendizado.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que Code Agents fazem muito bem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Criar testes automatizados&lt;/li&gt;
&lt;li&gt;Refatorar código repetitivo&lt;/li&gt;
&lt;li&gt;Sugerir melhorias&lt;/li&gt;
&lt;li&gt;Prototipar ideias rapidamente&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É absurdo a velocidade que conseguimos criar testes, refatorar e desenvolver.&lt;/p&gt;

&lt;p&gt;O problema começa quando ela deixa de ser a ferramenta e tratamos ele como nosso substituto cognitivo, esperando que ele resolva rápido e sozinho, o trabalho que é nosso.&lt;/p&gt;




&lt;h2&gt;
  
  
  O risco invisível: atrofia técnica e comodismo
&lt;/h2&gt;

&lt;p&gt;A dependência não acontece de forma brusca.&lt;/p&gt;

&lt;p&gt;Ela é silenciosa.&lt;/p&gt;

&lt;p&gt;Você começa a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pedir soluções prontas antes de ter pensado em como solucionar&lt;/li&gt;
&lt;li&gt;Deixar a IA decidir arquitetura&lt;/li&gt;
&lt;li&gt;Não consultar mais a documentação&lt;/li&gt;
&lt;li&gt;Confiar em abordagens sem entender 100% do que foi feito, só porque funciona&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nosso cérebro economiza energia sempre que pode.&lt;/p&gt;

&lt;p&gt;Se a gente parar de exercitar raciocínio técnico, ele enfraquece.&lt;/p&gt;




&lt;h2&gt;
  
  
  Um ponto importante
&lt;/h2&gt;

&lt;p&gt;É importante lembrar que somos profissionais utilizando uma ferramenta, e não alguém que transfere para a ferramenta a responsabilidade do próprio trabalho&lt;/p&gt;




&lt;h2&gt;
  
  
  Estratégias práticas para usar sem ficar dependente e ser mais assertivo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Analisar sua solução
&lt;/h3&gt;

&lt;p&gt;Antes de pedir solução para a IA, defina:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qual é o problema que quer solucionar&lt;/li&gt;
&lt;li&gt;Quais são as abordagens você utilizaria&lt;/li&gt;
&lt;li&gt;Quais as suas dúvidas a respeito dessa implementação, e quais as possíveis respostas pra essas dúvidas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depois use a IA para comparar, melhorar ou revisar.&lt;/p&gt;

&lt;p&gt;Isso mantém o raciocínio ativo.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Peça explicações técnicas
&lt;/h3&gt;

&lt;p&gt;Não peça apenas código.&lt;/p&gt;

&lt;p&gt;Peça:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Por que essa abordagem?&lt;/li&gt;
&lt;li&gt;Qual a complexidade?&lt;/li&gt;
&lt;li&gt;Existe alternativa mais performática e porque?&lt;/li&gt;
&lt;li&gt;Quais são os riscos dessa implementação?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Utilize o agente em mentor, não executor. Questione e aproveite para aprender&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Trabalhe em blocos pequenos
&lt;/h3&gt;

&lt;p&gt;Prompts grandes demais aumentam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alucinação&lt;/li&gt;
&lt;li&gt;Código inconsistente&lt;/li&gt;
&lt;li&gt;Erros arquiteturais&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dividir em partes mantém controle e entendimento.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Testes
&lt;/h3&gt;

&lt;p&gt;Além de gerar testes automatizados, podemos pedir sugestões de quais testes adicionar e como testar cada etapa que estamos desenvolvendo&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Não abandone a documentação
&lt;/h3&gt;

&lt;p&gt;Code Agents são ótimos para resumir docs.&lt;/p&gt;

&lt;p&gt;Mas é valido questionar de onde vem aquela informação e consultar a documentação original. Code agents podem ser excelentes professores, mas é sempre importante continuar validando as informações na documentação&lt;/p&gt;

&lt;p&gt;Dominar a documentação nos trás mais certeza e confiança&lt;/p&gt;




&lt;h2&gt;
  
  
  A mentalidade correta
&lt;/h2&gt;

&lt;p&gt;Code Agents não substituem desenvolvedores.&lt;/p&gt;

&lt;p&gt;São uma arma poderosa, mas não vão vencer as batalhas por nós.&lt;/p&gt;

&lt;p&gt;Eles podem ajudar a aumentar nosso nível técnico.&lt;/p&gt;

&lt;p&gt;O segredo está na maturidade de como usamos. Produtividade sem consciência vira dependência.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>productivity</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>SQL e Ruby: Explorando Banco de Dados Além do Rails ActiveRecord</title>
      <dc:creator>Luiz Fernando Puri</dc:creator>
      <pubDate>Wed, 06 Nov 2024 17:29:06 +0000</pubDate>
      <link>https://dev.to/fernandopuri_dev/sql-e-ruby-explorando-banco-de-dados-alem-do-rails-activerecord-4096</link>
      <guid>https://dev.to/fernandopuri_dev/sql-e-ruby-explorando-banco-de-dados-alem-do-rails-activerecord-4096</guid>
      <description>&lt;p&gt;Na carreira como Desenvolvedor de Software, o conhecimento de SQL (Structured Query Language) é uma habilidade importante. Estando presente no nosso dia a dia de trabalho ou sendo necessária apenas em momentos esporádicos, é um conhecimento que vez ou outra vamos utilizar. Para nós, profissionais da área, é melhor saber do que não saber. Entender SQL pode nos trazer novas possibilidades, nos permitir ter um controle maior sobre as operações de dados e nos trazer mais oportunidades profissionais.&lt;/p&gt;

&lt;p&gt;Embora o Rails facilite o nosso trabalho, simplificando a interação com o banco de dados por meio do ActiveRecord, é comum ficarmos dependentes dessa conveniência oferecida. Acredito que isso ocorra com o uso de outros ORMs, e não é nossa culpa. Muitas vezes trabalhamos em ambientes dinâmicos, de muitas entregas, e em nosso tempo de estudo focamos em aprender novas tecnologias. Dessa forma, podemos esquecer de praticar conhecimentos que já estudamos na faculdade ou no início dos nossos estudos de programação. E por ser um conhecimento que não está sendo utilizado com frequência podemos acabar esquecendo. Assim como um músculo que atrofia se deixar de fazer exercícios, essas habilidades também podem atrofiar.&lt;/p&gt;

&lt;p&gt;Neste artigo vamos explorar como fazer queries SQL puro no Rails, a utilização de Banco de Dados no Ruby sem ActiveRecord, e dicas para praticar o conhecimento de SQL&lt;/p&gt;

&lt;h2&gt;
  
  
  Como e quando fazer queries SQL puro no Rails?
&lt;/h2&gt;

&lt;p&gt;Apesar do ActiveRecord cuidar da maior parte das nossas interações com o banco de dados, há certos momentos que escrever consultas diretas em SQL se torna mais interessante. Por exemplo, em casos onde exista a necessidade de realizar consultas complexas que envolvam joins entre várias tabelas, agregações e subconsultas, é possível que o ActiveRecord seja mais difícil de usar, apresente limitações e tenha menor desempenho. Isso é algo que acontece no uso de ORMs, em situações específicas pode ser mais trabalhoso entender como a ORM realiza determinada consulta, do que escrever diretamente em SQL. Desempenho, Complexidade e Limitações são pontos importantes, que podem tornar necessário o uso das queries feitas diretamente no banco de dados.&lt;/p&gt;

&lt;p&gt;Para executar instruções SQL no rails podemos utilizar o método &lt;code&gt;ActiveRecord::Base.connection.execute()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SELECT * FROM users WHERE age &amp;gt; 18"&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Caso nossa query tenha um retorno, ele será um objeto, de tipo result do banco de dados em uso, que poderá ser iterado&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"User ID: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, Name: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, Age: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'age'&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="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Um detalhe importante:&lt;/strong&gt; Da versão do &lt;strong&gt;Rails 7.2 em diante&lt;/strong&gt;, o &lt;code&gt;ActiveRecord::Base.connection&lt;/code&gt; foi descontinuado. Nessas versões recentes ele &lt;strong&gt;foi substituído por &lt;code&gt;ActiveRecord::Base.lease_connection&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilizando Banco de Dados no Ruby sem ActiveRecord
&lt;/h2&gt;

&lt;p&gt;Em aplicações Ruby com Sinatra é possível também utilizar a Gem do ActiveRecord para fazer esse papel de interação com o banco de dados. Mas e se quisermos fazer essa conexão sem o uso do ActiveRecord e ORMs?&lt;/p&gt;

&lt;p&gt;Para mostrar um exemplo de conexão e interação com o banco de dados fiz um script Ruby puro utilizando a Gem &lt;code&gt;pg&lt;/code&gt;. Essa gem faz a comunicação entre Ruby e o SGBD PostgreSQL. O script de exemplo pode ser acessado no repositório do &lt;a href="https://github.com/FernandoInkaPuri/postgres_training/blob/main/pg_training.rb" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse Script é composto de alguns métodos, e o bloco que o executa é este:&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;begin&lt;/span&gt;
  &lt;span class="n"&gt;start_database&lt;/span&gt;

  &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connect_to_database&lt;/span&gt;

  &lt;span class="n"&gt;create_pets_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;populate_pets_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;show_pets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;PG&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Erro: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;ensure&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O primeiro método chamado é o &lt;code&gt;start_database&lt;/code&gt;. Esse método faz uma validação para saber se o container postgres já existe. Caso não exista, ele executa um comando para criar um container docker da imagem postgres com o nome do banco de dados &lt;code&gt;training_db&lt;/code&gt;, usuário &lt;code&gt;trainer&lt;/code&gt; e senha &lt;code&gt;secret&lt;/code&gt;, e mapeia a porta do container para a porta 5433 . Se existir ele apenas sobe o container:&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;start_database&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Iniciando container de banco de dados'&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;container_exists?&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'docker start postgres_training'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"docker run --name postgres_training -e POSTGRES_USER=trainer -e POSTGRES_PASSWORD=secret -e POSTGRES_DB=training_db -p 5433:5432 -d postgres"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 
  &lt;span class="nb"&gt;sleep&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&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;Após isso é chamado o método &lt;code&gt;connect_to_database&lt;/code&gt; para criar a conexão com o banco de dados. O método contém o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect_to_database&lt;/span&gt;
  &lt;span class="c1"&gt;# Alias para  PG::Connection.new e PG::Connection.open&lt;/span&gt;
  &lt;span class="no"&gt;PG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="ss"&gt;dbname: &lt;/span&gt;&lt;span class="s1"&gt;'training_db'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;user: &lt;/span&gt;&lt;span class="s1"&gt;'trainer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="s1"&gt;'secret'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;host: &lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;port: &lt;/span&gt;&lt;span class="mi"&gt;5433&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos nos conectar a um banco de dados usando o método &lt;code&gt;PG.connect&lt;/code&gt;, que seria o mesmo que usar &lt;code&gt;PG::Connection.new&lt;/code&gt; ou &lt;code&gt;PG::Connection.open&lt;/code&gt;. Nele passamos os argumentos do banco de dados. Nesse nosso exemplo passamos as informações definidas no nosso container postgres do docker e a porta que foi mapeada. Por padrão a porta do postgres é 5432.&lt;/p&gt;

&lt;p&gt;Em seguida armazenamos essa conexão feita em &lt;code&gt;connect_to_database&lt;/code&gt; na variável &lt;code&gt;conn&lt;/code&gt; para utilizar essa conexão em outros métodos. Depois é chamado o método &lt;code&gt;create_pets_table(conn)&lt;/code&gt;. Nele utilizamos o método &lt;code&gt;.exec&lt;/code&gt;, para executar nossas instruções SQL:&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;create_pets_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"CREATE TABLE IF NOT EXISTS pets (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    species VARCHAR(100),
    age INT
  );"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Tabela de pets criada!'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse método &lt;code&gt;.exec&lt;/code&gt; é responsaǘel por fazer queries SQL. Em caso de sucesso retorna um objeto PG::Result com os resultados da query, e em caso de falha retorna um PG::Error. &lt;/p&gt;

&lt;p&gt;Na gem PG também temos o método &lt;code&gt;.exec_params&lt;/code&gt;, muito útil se precisamos fazer uma consulta usando parâmetros. Podemos ver seu uso seguindo o script de exemplo, quando chamamos &lt;code&gt;populate_pets_table(conn)&lt;/code&gt;, que contém o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;populate_pets_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'ScoobyDoo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Dog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Pikachu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Pokemon'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Noturno'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Cat'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Tanguá'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Monkey'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

  &lt;span class="n"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec_params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"INSERT INTO pets (name, species, age) VALUES ($1, $2, $3);"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Dados inseridos na tabela de pets!'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Nesse método tentei fazer uma ideia de seeds para popular a tabela pets. No trecho &lt;code&gt;conn.exec_params("INSERT INTO pets (name, species, age) VALUES ($1, $2, $3);", pet)&lt;/code&gt;, o &lt;code&gt;exec_params&lt;/code&gt; faz uma query para inserir dados na tabela pets: nos campos name, species e age serão inseridos os valores $1, $2 e $3.&lt;/p&gt;

&lt;p&gt;Esses valores que vão ser inseridos devem ser informados em um array, que nos caso é a variável pet. Nesse bloco que está sendo iterado será executado primeiro &lt;code&gt;conn.exec_params("INSERT INTO pets (name, species, age) VALUES ($1, $2, $3);", ['ScoobyDoo', 'Dog', 5])&lt;/code&gt;, depois &lt;code&gt;conn.exec_params("INSERT INTO pets (name, species, age) VALUES ($1, $2, $3);", ['Pikachu', 'Pokemon', 3])&lt;/code&gt; e assim por diante.&lt;/p&gt;

&lt;p&gt;Seguindo o código do script, é chamado o método &lt;code&gt;show_pets(conn)&lt;/code&gt; que usa o método exec para fazer uma querie buscando tudo na tabela pets e armazenando em uma variável que será iterada depois para printar os registros: &lt;code&gt;result = conn.exec("SELECT * FROM pets")&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No fim do script temos um &lt;code&gt;rescue&lt;/code&gt; que utiliza o PG::Error para fazer a tratativa de erros que possam ocorrer na nossa conexão e interação com o banco de dados. E o &lt;code&gt;ensure&lt;/code&gt; para garantir que a conexão será encerrada mesmo que ocorra algum erro.&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;rescue&lt;/span&gt; &lt;span class="no"&gt;PG&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Erro: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;ensure&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Encerrar a conexão é uma boa prática, pois garante a liberação de recursos do sistema, evita problemas de desempenho e vazamento de informação. &lt;/p&gt;

&lt;h2&gt;
  
  
  Dicas para praticar SQL
&lt;/h2&gt;

&lt;p&gt;Existem sites que podemos praticar, como &lt;a href="https://www.sqlteaching.com/" rel="noopener noreferrer"&gt;SQL Teaching&lt;/a&gt;, &lt;a href="https://sqlzoo.net/wiki/SQL_Tutorial" rel="noopener noreferrer"&gt;SQLZoo&lt;/a&gt; e &lt;a href="https://www.w3schools.com/sql/default.asp" rel="noopener noreferrer"&gt;W3Schools&lt;/a&gt;. Também jogos como o &lt;a href="https://mystery.knightlab.com/" rel="noopener noreferrer"&gt;SQL Murder Mystery&lt;/a&gt;. Além disso podemos baixar o &lt;a href="https://www.mysql.com/products/workbench/" rel="noopener noreferrer"&gt;MySQL Workbench&lt;/a&gt; ou &lt;a href="https://www.pgadmin.org/" rel="noopener noreferrer"&gt;pgAdmin&lt;/a&gt;, que são ferramentas gráficas onde podemos explorar os comandos SQL, de forma mais intuitiva e visual.&lt;/p&gt;

&lt;p&gt;No mesmo &lt;a href="https://github.com/FernandoInkaPuri/postgres_training" rel="noopener noreferrer"&gt;repositório&lt;/a&gt; desse script utilizado como exemplo, tem outro arquivo, &lt;code&gt;learning_sql.rb&lt;/code&gt;, onde fiz um script interativo com uma interface que permite o usuário executar consultas SQL e aprender a fazer queries de forma prática.&lt;/p&gt;

&lt;p&gt;Sei que podemos acabar esquecendo os conhecimentos se não colocarmos em prática, e no caso do desenvolvimento no Rails pode ser comum esquecermos o conhecimento SQL, já que ele faz as queries por nós. Fiz esse artigo com o intuito de trazer um compilado de informações que podem ajudar outros Devs que eventualmente enfrentarão esse problema.&lt;/p&gt;

&lt;p&gt;Agradeço seu tempo e sua leitura! E vamos por a mão &lt;del&gt;na massa&lt;/del&gt; &lt;strong&gt;no código&lt;/strong&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Entendendo Active Record, a Gem do Rails e o Design Pattern</title>
      <dc:creator>Luiz Fernando Puri</dc:creator>
      <pubDate>Wed, 23 Oct 2024 20:09:33 +0000</pubDate>
      <link>https://dev.to/fernandopuri_dev/entendendo-active-record-a-gem-do-rails-e-o-design-pattern-2hp7</link>
      <guid>https://dev.to/fernandopuri_dev/entendendo-active-record-a-gem-do-rails-e-o-design-pattern-2hp7</guid>
      <description>&lt;p&gt;Rails é um dos frameworks mais populares em aplicações web, não apenas pela sua capacidade de acelerar o desenvolvimento, mas também por seus componentes robustos, como o Active Record, que transforma a maneira como interagimos com bancos de dados. Um dos motivos de sua popularização foi a produtividade que o Rails trouxe, permitindo o desenvolvimento mais rápido de aplicações utilizando menos código.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Gem Active Record
&lt;/h2&gt;

&lt;p&gt;O Rails nos fornece uma classe base, &lt;code&gt;ActiveRecord::Base&lt;/code&gt;, que nos permite associar classes (models) às tabelas do banco de dados. É através dessa associação e atuação da gem que conseguimos manipular os dados a partir do objeto. Isso torna possível o uso que estamos acostumados, de atualizar informações no banco de dados através dos objetos, em vez de escrever queries SQL.&lt;/p&gt;

&lt;p&gt;Por exemplo, usamos:&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;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;age: &lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;favorite_color: &lt;/span&gt;&lt;span class="s1"&gt;'blue'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;country_id: &lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em vez de:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;favorite_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;country_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porém o Active Record não é apenas uma gem do Rails. Active Record é um Design Pattern. Um padrão que lida com a camada de persistência dos dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Active Record Pattern
&lt;/h2&gt;

&lt;p&gt;Esse padrão foi proposto por Martin Fowler no livro "Patterns of Enterprise Application". Em seu site podemos encontrar essa explicação sobre o padrão:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Um objeto que encapsula uma linha em uma tabela ou exibição de banco de dados, encapsula o acesso ao banco de dados e adiciona lógica de domínio a esses dados.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Active Record é um padrão de Mapeamento Objeto-Relacional (ORM). Com a popularização das linguagens do paradigma Orientado a Objetos percebeu-se que era gasto muito tempo desenvolvendo queries SQL. A partir disso, nos anos 90 surge o conceito de ORM, essa técnica/abordagem para resolver esse problema.&lt;/p&gt;

&lt;p&gt;No padrão Active Record cada model é associado a uma tabela e cada instância (objeto) dessa classe é equivalente a uma linha dessa tabela. Esse objeto é responsável por suas próprias operações de persistência, além de manipular seus próprios dados (diferente do padrão Data Mapper, onde a lógica de persistência é feita por outro objeto próprio pra isso)&lt;/p&gt;

&lt;h2&gt;
  
  
  Principais atuações da Gem Active Record no Rails
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Convenção sobre configuração:&lt;/strong&gt; Por convenção, o models herdam de ApplicationRecord que herda da classe &lt;code&gt;ActiveRecord::Base&lt;/code&gt;. Dessa forma o mapeamento é automatizado entre classes e tabelas, atributos e colunas. Caso tenhamos um model chamado ‘BookClub’  o ActiveRecord irá associar esse modelo à uma tabela com o nome ‘book_clubs’. Enquanto o model segue o padrão de nomenclatura CapitalCase, a tabela segue o padrão snake_case no plural.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Associações entre objetos:&lt;/strong&gt; Podemos definir associações entres os objetos de forma simples através de métodos de classe como:&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;has_many&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;has_one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;belongs_to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;has_and_belongs_to_many&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Regras de validação:&lt;/strong&gt; Disponibiliza métodos que nos permite adicionar validações de forma 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;acceptance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;confirmation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comparison&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inclusion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numericality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;presence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uniqueness&lt;/span&gt; &lt;span class="c1"&gt;# E outros&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E também definir condições para essas validações ou adicionar validações customizadas através dos métodos:&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;if&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;validate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Callbacks:&lt;/strong&gt; Disponibiliza métodos de retorno de chamada para todo o ciclo de vida (instanciação, salvamento, destruição, validação, etc.):&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;before_validation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;before_save&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;before_create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;after_create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after_save&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;before_update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after_update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;before_destroy&lt;/span&gt; &lt;span class="n"&gt;etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso nos permite adicionar código para um comportamento desejado, em um momento específico do ciclo de vida do objeto (Porém use com moderação, usar callbacks em excesso pode te trazer dor de cabeça depois)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transactions:&lt;/strong&gt;&lt;br&gt;
Que são blocos de proteção, onde as instruções SQL só são aplicadas se todas elas puderem ser concluídas com sucesso. O exemplo mais conhecido talvez seja o de uma transação financeira&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;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;david&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withdrawal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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;&lt;strong&gt;Abstração de banco de dados por meio de adaptadores simples:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Gem Active Record já tem um suporte integrado para MySQL, PostgreSQL e SQLite3 através de adaptadores. É possível usar outros bancos como Oracle, SQLServer etc mas talvez seja necessário o uso de gems&lt;/p&gt;

&lt;p&gt;Caso tenha interesse em saber mais sobre o ActiveRecord, pode encontrar informações interessantes na &lt;a href="https://github.com/rails/rails/tree/main/activerecord" rel="noopener noreferrer"&gt;documentação da gem no github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este está sendo o primeiro artigo que estou escrevendo. Agredeço pelo tempo que tirou para ler!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
