<?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: Kevin Expósito</title>
    <description>The latest articles on DEV Community by Kevin Expósito (@kexposito).</description>
    <link>https://dev.to/kexposito</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%2F599172%2F6f2a4fa6-042e-4854-9f8e-fd6349dac255.jpg</url>
      <title>DEV Community: Kevin Expósito</title>
      <link>https://dev.to/kexposito</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kexposito"/>
    <language>en</language>
    <item>
      <title>Emberjs Data Model Migration Guide</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Thu, 04 Sep 2025 03:48:31 +0000</pubDate>
      <link>https://dev.to/kexposito/emberjs-data-model-migration-guide-jk</link>
      <guid>https://dev.to/kexposito/emberjs-data-model-migration-guide-jk</guid>
      <description>&lt;p&gt;This guide covers migrating Ember Data models from the legacy syntax to the modern one.&lt;/p&gt;

&lt;p&gt;Useful docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://guides.emberjs.com/v3.8.0/models/defining-models/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Example of old Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://guides.emberjs.com/v6.3.0/models/defining-models/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Example of new Model&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Basic Migration Pattern&lt;/li&gt;
&lt;li&gt;Attributes Migration&lt;/li&gt;
&lt;li&gt;Relationships Migration&lt;/li&gt;
&lt;li&gt;Computed Properties Migration&lt;/li&gt;
&lt;li&gt;Testing Migrated Models&lt;/li&gt;
&lt;li&gt;Complete Example&lt;/li&gt;
&lt;li&gt;Best Practices&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The migration involves converting from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DS.Model.extend({...})&lt;/code&gt; → &lt;code&gt;export default class ModelName extends Model&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;attr()&lt;/code&gt; → &lt;code&gt;@attr()&lt;/code&gt; decorator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;belongsTo()&lt;/code&gt; → &lt;code&gt;@belongsTo()&lt;/code&gt; decorator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hasMany()&lt;/code&gt; → &lt;code&gt;@hasMany()&lt;/code&gt; decorator&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Basic Migration Pattern
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before (Legacy Syntax)
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  After (Modern Syntax)
&lt;/h3&gt;

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




&lt;h2&gt;
  
  
  Attributes Migration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Simple Attributes
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  Attributes with Default Values
&lt;/h3&gt;

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




&lt;h2&gt;
  
  
  Relationships Migration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  BelongsTo Relationships
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  HasMany Relationships
&lt;/h3&gt;

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




&lt;h2&gt;
  
  
  Computed Properties Migration
&lt;/h2&gt;

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




&lt;h2&gt;
  
  
  Testing Migrated Models
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Basic Test Setup
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  Testing Attributes
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  Testing Computed Properties
&lt;/h3&gt;

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




&lt;h2&gt;
  
  
  Complete Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before (Legacy Model)
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  After (Modern Model)
&lt;/h3&gt;

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

</description>
      <category>blogs</category>
    </item>
    <item>
      <title>Git Rebase vs Git Merge ¿cuál usar y cuándo?</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Thu, 07 Aug 2025 04:29:45 +0000</pubDate>
      <link>https://dev.to/kexposito/git-rebase-vs-git-merge-cual-usar-y-cuando-1gka</link>
      <guid>https://dev.to/kexposito/git-rebase-vs-git-merge-cual-usar-y-cuando-1gka</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm93dsxqp6b9isosysw1d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm93dsxqp6b9isosysw1d.gif" alt="git rebase vs git merge" width="1080" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando trabajamos en Git, eventualmente llega el momento de integrar cambios entre ramas. Dos comandos comunes para esto son &lt;a href="https://git-scm.com/docs/git-merge" rel="noopener noreferrer"&gt;&lt;code&gt;git merge&lt;/code&gt;&lt;/a&gt; y &lt;a href="https://git-scm.com/docs/git-rebase" rel="noopener noreferrer"&gt;&lt;code&gt;git rebase&lt;/code&gt;&lt;/a&gt;, y aunque ambos buscan unificar historias, lo hacen de maneras muy diferentes.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;git merge&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Este comando &lt;strong&gt;une dos ramas&lt;/strong&gt; creando un nuevo commit de «merge» que representa esa unión.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Historial explícito&lt;/strong&gt; : muestra claramente cuándo y cómo se fusionaron ramas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seguro&lt;/strong&gt; : mantiene la historia original tal cual, sin reescribirla.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ideal para ramas públicas&lt;/strong&gt;  &lt;strong&gt;o de uso continuo&lt;/strong&gt; : como &lt;code&gt;main&lt;/code&gt; o &lt;code&gt;develop&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Contras:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;El historial puede volverse &lt;strong&gt;más ruidoso&lt;/strong&gt; con muchos commits de merge.&lt;/li&gt;
&lt;li&gt;Menos lineal: puede dificultar la lectura cuando hay muchas ramas.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;git rebase&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Este comando &lt;strong&gt;reaplica los commits de una rama sobre otra&lt;/strong&gt; , como si se hubieran creado después del último commit de destino.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Historial limpio y lineal&lt;/strong&gt; : ideal para revisiones más claras.&lt;/li&gt;
&lt;li&gt;Útil para &lt;strong&gt;«reubicar» cambios&lt;/strong&gt; antes de integrarlos (ej. cuando trabajás en una feature y querés mantenerla actualizada con &lt;code&gt;main&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Contras:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reescribe la historia&lt;/strong&gt; : peligroso si ya compartiste esa rama con otros.&lt;/li&gt;
&lt;li&gt;Puede ser más &lt;strong&gt;complejo de entender&lt;/strong&gt; al principio.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ¿Cuándo usar cada uno?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situación&lt;/th&gt;
&lt;th&gt;Usar&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Quiero mantener el historial tal como ocurrió&lt;/td&gt;
&lt;td&gt;&lt;code&gt;merge&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quiero un historial limpio y lineal&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rebase&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Estoy colaborando y ya compartí la rama&lt;/td&gt;
&lt;td&gt;&lt;code&gt;merge&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Estoy trabajando en una feature localmente&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rebase&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Tip Final
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Usá &lt;code&gt;rebase&lt;/code&gt; para limpiar tu historia &lt;strong&gt;antes&lt;/strong&gt; de hacer merge, pero evitá hacerlo en ramas que otros ya estén usando.&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>git</category>
    </item>
    <item>
      <title>Difference between the ^ and ~ in package.json</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Wed, 23 Apr 2025 02:38:06 +0000</pubDate>
      <link>https://dev.to/kexposito/difference-between-the-and-in-packagejson-2be5</link>
      <guid>https://dev.to/kexposito/difference-between-the-and-in-packagejson-2be5</guid>
      <description>&lt;h2&gt;
  
  
  ^ vs ~
&lt;/h2&gt;

&lt;p&gt;If you’ve ever looked at a &lt;code&gt;package.json&lt;/code&gt; and wondered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"lodash": "^4.17.21"

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

&lt;/div&gt;



&lt;p&gt;…or maybe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"express": "~4.18.2"

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

&lt;/div&gt;



&lt;p&gt;And thought &lt;em&gt;what’s with the hat and the squiggly line?&lt;/em&gt;, you’re not alone. Let’s decode what these characters do, and when to use them.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 TL;DR: What do &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;~&lt;/code&gt; mean in package.json?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Allows Updates To&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Can Upgrade To&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minor &amp;amp; Patch&lt;/td&gt;
&lt;td&gt;&lt;code&gt;^1.2.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1.3.0&lt;/code&gt;, &lt;code&gt;1.2.4&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Patch only&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~1.2.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1.2.4&lt;/code&gt;, not &lt;code&gt;1.3&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Exact version&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.2.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only &lt;code&gt;1.2.3&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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




&lt;h2&gt;
  
  
  &lt;code&gt;^&lt;/code&gt; (Caret)
&lt;/h2&gt;

&lt;p&gt;The caret means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;«Install this version &lt;strong&gt;or anything newer that doesn’t break major version compatibility&lt;/strong&gt;.»&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This follows &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;Semantic Versioning (SemVer)&lt;/a&gt;, where a &lt;strong&gt;major.minor.patch&lt;/strong&gt; version tells you the scope of the changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"axios": "^1.3.2"

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

&lt;/div&gt;



&lt;p&gt;Can update to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ 1.3.3&lt;/li&gt;
&lt;li&gt;✅ 1.9.9&lt;/li&gt;
&lt;li&gt;❌2.0.0 (major version change)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 It’s the default versioning npm uses when you run &lt;code&gt;npm install axios@1.3.2&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;~&lt;/code&gt; (Tilde)
&lt;/h2&gt;

&lt;p&gt;The tilde means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;«Install this version or any newer patch within the &lt;strong&gt;same minor version&lt;/strong&gt;.»&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"axios": "~1.3.2"

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

&lt;/div&gt;



&lt;p&gt;Can update to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ 1.3.3&lt;/li&gt;
&lt;li&gt;✅ 1.3.9&lt;/li&gt;
&lt;li&gt;❌ 1.4.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is much more conservative — perfect for when you don’t want unexpected changes sneaking into your builds.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Why This Matters: The Hidden Danger
&lt;/h2&gt;

&lt;p&gt;Imagine this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You deploy your app today with &lt;code&gt;^1.3.2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A week later, &lt;code&gt;1.4.0&lt;/code&gt; is released with a subtle change that breaks your edge case.&lt;/li&gt;
&lt;li&gt;You run &lt;code&gt;npm install&lt;/code&gt;, and suddenly your app is acting weird.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Surprise! 🎉&lt;/p&gt;

&lt;p&gt;Unless you locked dependencies or used &lt;code&gt;~&lt;/code&gt;, you’re getting updates whether you asked for them or not.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hopdsh2cbysmccmjs7y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hopdsh2cbysmccmjs7y.gif" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Pros and Cons
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Keeps you up-to-date easily&lt;/td&gt;
&lt;td&gt;Risk of breakage in minor updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Safer and more predictable builds&lt;/td&gt;
&lt;td&gt;Can miss out on minor improvements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Total control (exact version)&lt;/td&gt;
&lt;td&gt;No updates unless manual&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🛠 When to Use What?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use &lt;code&gt;^&lt;/code&gt; when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You’re building a library or want the latest stable versions&lt;/li&gt;
&lt;li&gt;You’re okay with minor version bumps and trust the maintainers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use &lt;code&gt;~&lt;/code&gt; when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stability is critical (e.g. production apps)&lt;/li&gt;
&lt;li&gt;You want tight control over updates&lt;/li&gt;
&lt;li&gt;You’ve been burned before&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use no symbol when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You want full determinism&lt;/li&gt;
&lt;li&gt;You’re building dockerized / reproducible builds&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Bonus: How to Check What’s Actually Installed
&lt;/h2&gt;

&lt;p&gt;To see what version was installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm list &amp;lt;package-name&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;An alternative to this is just checking your &lt;code&gt;yarn.lock&lt;/code&gt; or &lt;code&gt;package-lock.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To find out what’s outdated:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧵 Conclusion
&lt;/h2&gt;

&lt;p&gt;Choosing between &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;~&lt;/code&gt; might seem like a small detail, but it can mean the difference between a calm deploy and hours of debugging.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;^&lt;/code&gt; if you like to live a little.&lt;br&gt;&lt;br&gt;
Use &lt;code&gt;~&lt;/code&gt; if you like sleeping at night.&lt;br&gt;&lt;br&gt;
Use no symbol if you’re preparing for war ⚔.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Related Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;Semantic Versioning Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies" rel="noopener noreferrer"&gt;npm semver docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;La entrada &lt;a href="https://positionsticky.com/blogs/difference-between-caret-and-tilde/" rel="noopener noreferrer"&gt;Difference between the ^ and ~ in package.json&lt;/a&gt; se publicó primero en &lt;a href="https://positionsticky.com" rel="noopener noreferrer"&gt;Position Sticky&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>yarn</category>
      <category>npm</category>
    </item>
    <item>
      <title>¿Cómo Agregar Parámetros Condicionalmente en Componentes React?</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Wed, 10 Jan 2024 16:17:30 +0000</pubDate>
      <link>https://dev.to/kexposito/como-agregar-parametros-condicionalmente-en-componentes-react-nmg</link>
      <guid>https://dev.to/kexposito/como-agregar-parametros-condicionalmente-en-componentes-react-nmg</guid>
      <description>&lt;p&gt;En este blog, exploraremos técnicas avanzadas para agregar parámetros condicionalmente en componentes React de manera eficiente, enfocándonos en mejorar la legibilidad y mantenibilidad del código.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Introducción: Desarrollo React Centrado en la Claridad del Código&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;En el desarrollo con React, la gestión efectiva de parámetros condicionalmente es esencial para mantener un código claro y fácil de entender. Vamos a explorar cómo mejorar este proceso utilizando un ejemplo de un botón en React.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Desafío Común: Parámetros Condicionalmente en Componentes React&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A menudo, necesitamos manejar condicionalmente los parámetros de nuestros componentes. Consideremos el siguiente ejemplo de un &lt;a href="https://chakra-ui.com/docs/components/button/usage#custom-button"&gt;Botón de la librería Chakra UI&lt;/a&gt; en React a la cual le queremos agregar que si cierta condición booleana &lt;strong&gt;isActive&lt;/strong&gt; es verdadera, que se aplique el estilo &lt;strong&gt;{bg: white}&lt;/strong&gt; (lo cual significa que el backgroundColor sea blanco)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--22Jmgvea--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://positionsticky.com/wp-content/uploads/2024/01/image-1-1024x792.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--22Jmgvea--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://positionsticky.com/wp-content/uploads/2024/01/image-1-1024x792.png" alt="" width="800" height="619"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Code without changes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Si bien esto funciona, no es lo mas lindo agradable de ver. Por lo que podemos agregar condicionalmente estos valores de otra forma.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Mejora Legibilidad y Mantenibilidad: Utilizando Parámetros Condicionalmente&lt;/strong&gt; en Componentes
&lt;/h2&gt;

&lt;p&gt;Refactorizar el código utilizando parámetros condicionalmente simplifica la lógica y mejora la legibilidad:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AacnJCUE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://positionsticky.com/wp-content/uploads/2024/01/image-960x1024.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AacnJCUE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://positionsticky.com/wp-content/uploads/2024/01/image-960x1024.png" alt="" width="800" height="853"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Apply conditional style in component&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lo que hicimos aqui fue agrupar todas las condiciones que queremos que sean aplicadas una vez &lt;strong&gt;isActive&lt;/strong&gt; sea verdadera en un objeto llamado &lt;strong&gt;conditionalButtonStyle&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Ventajas de Utilizar Parámetros Condicionalmente en Componentes:&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Legibilidad Mejorada:&lt;/strong&gt; La refactorización simplifica el código, haciendo que la lógica condicional sea más clara y fácil de entender.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mantenimiento Eficiente:&lt;/strong&gt; Los parámetros condicionalmente permiten ajustes y actualizaciones centralizadas, facilitando el mantenimiento del código a lo largo del tiempo. Además que permiten agregar un bloque de parámetros a partir de la misma.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusión: Desarrollo Inteligente para Mejorar Claridad del Código en React&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;En conclusión, agregar parámetros condicionales a los componentes React mejora la calidad del desarrollo y facilita el mantenimiento del código. Al adoptar estas prácticas, optimizamos nuestro código para que sea más legible y fácil de gestionar. ¡A seguir desarrollando con claridad en mente! ¡Hasta la próxima!&lt;/p&gt;

&lt;p&gt;Si te gustó, no olvides de suscribirte para más contenido!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>El día que ordené un Test en PedidosYa!</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Wed, 31 May 2023 14:47:02 +0000</pubDate>
      <link>https://dev.to/kexposito/el-dia-que-ordene-un-test-en-pedidosya-2j8d</link>
      <guid>https://dev.to/kexposito/el-dia-que-ordene-un-test-en-pedidosya-2j8d</guid>
      <description>&lt;p&gt;🍔  Como alguien que disfruta buscar opciones deliciosas de comidas, me he convertido en un fiel visitante de PedidosYa, siempre dispuesto a descubrir nuevos sabores y locales. Se podría decir que muchas veces entro a la aplicación por hobby, solo para ver que encuentro (y termino pidiendo comida a pesar de ya tener lo que voy a comer).&lt;/p&gt;

&lt;p&gt;Y déjenme contarles sobre una de los tantos viernes a la noche que me encontré con un Test de Integración en la lista de locales que tenia delivery a mi dirección.&lt;/p&gt;

&lt;p&gt;A partir de determinada hora, la aplicacion, muestra siempre los mismos locales fieles a las personas nocturnas (ejemplo Mafalda) pero esta noche me encontre con otro local, lo cual me llamo la atencion, particularmente su nombre “Test POS Integration”.&lt;/p&gt;




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




&lt;p&gt;🤔 Enseguida me di cuenta que algo no andaba bien, pero me dio curiosidad de ver que ofrecía este local y ver hasta donde podía llegar.&lt;/p&gt;

&lt;p&gt;Por lo que decidí entrar y ver que comidas ofrecía, y al entrar observamos precios y nombres bastante locos, como por ejemplo: “Test de banana con coma”, “Hamburguesa con 3 papas”, “Agua para adultos”.&lt;/p&gt;




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




&lt;p&gt;🔍 Mi curiosidad es grande, por lo que decidí realizar un pedido para ver que pasaba, entonces me pedi un Combo Agrandado Wrap de Carne y efectivamente el pedido se realizo correctamente.&lt;/p&gt;




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




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




&lt;p&gt;Luego de varios minutos, el pedido nunca salió del estado de CONFIRMACION… supongo que tendrán un timeout, para evitar que el local tenga un pedido en espera a ser confirmado, por lo que el pedido fue cancelado automáticamente.&lt;/p&gt;




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




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




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




&lt;p&gt;Mientras esperaba el pedido, intente comunicarme con Ayuda en linea para poder notificar de esta distracción, pero no fue posible.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;plot twist: no me dieron ningún cupón&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt;&lt;br&gt;
Guardé el link del local de comida y parece que sigue estando activo&lt;/p&gt;




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




</description>
      <category>programming</category>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>Comandos básicos para aprender Git</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Fri, 13 Jan 2023 03:46:14 +0000</pubDate>
      <link>https://dev.to/kexposito/comandos-basicos-para-aprender-git-32b</link>
      <guid>https://dev.to/kexposito/comandos-basicos-para-aprender-git-32b</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzt3huwn4j3405vbjqvm3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzt3huwn4j3405vbjqvm3.png" alt="Image description" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducción:
&lt;/h2&gt;

&lt;p&gt;Personalmente a la hora de aprender Git, muchas me vi abrumado por tantos comandos que veía en su &lt;a href="https://git-scm.com/docs" rel="noopener noreferrer"&gt;web&lt;/a&gt; y aún más cuando cada uno de estos comandos podemos observar que tienen mil parámetros diferentes! (ver ejemplo de &lt;a href="https://git-scm.com/docs/git-merge" rel="noopener noreferrer"&gt;merge&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Y es por esa razón que traigo esta mini lista de comandos básicos para aprender Git que nos van a ayudar a movernos tranquilamente&lt;/p&gt;

&lt;h2&gt;
  
  
  Listado:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Crear un repositorio
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Agregar archivos modificados a staging
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add &amp;lt;nombre-del-archivo&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ver archivos modificados
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Crear una nueva rama en Git
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b &amp;lt;nueva-rama&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cambiarme a una rama en Git
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout &amp;lt;otra-rama&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;otra forma en la que podemos hacerlo es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git switch &amp;lt;otra-rama&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Crear un commit con los archivos de staging
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m "Esto es un mensaje"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deshacer commits (dejando los archivos en dirty)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git reset &amp;lt;commit-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deshacer commits (borrando todo)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git reset --HARD &amp;lt;commit-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pushear una nueva rama
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin &amp;lt;rama-actual&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Actualizar rama actual con origin:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git pull origin &amp;lt;rama&amp;gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Actualizar una rama con lo ultimo de main (si aun no subiste esa rama):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git pull origin main
git checkout &amp;lt;rama&amp;gt;
git rebase main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Actualizar rama con lo ultimo de main (si ya subiste los cambios)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git pull origin main
git checkout &amp;lt;branch-name&amp;gt;
git merge main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esta lista de comandos básicos vas a poder aprender git y realizar la gran mayoría de las cosas que quieras hacer!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpc4ths8cllc4i665owdj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpc4ths8cllc4i665owdj.gif" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La entrada &lt;a href="https://positionsticky.com/blogs/comandos-basicos-para-aprender-git/" rel="noopener noreferrer"&gt;Comandos básicos para aprender Git&lt;/a&gt; se publicó primero en &lt;a href="https://positionsticky.com" rel="noopener noreferrer"&gt;Position Sticky&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Creating a Twitter Bot with Phoenix</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Tue, 13 Dec 2022 15:45:53 +0000</pubDate>
      <link>https://dev.to/kexposito/creating-a-twitter-bot-with-phoenix-2idc</link>
      <guid>https://dev.to/kexposito/creating-a-twitter-bot-with-phoenix-2idc</guid>
      <description>&lt;p&gt;I started this blog in order to learn how to use Twitter API and also because i love going to the cinema 🙌. Im from Uruguay 🇺🇾, and here we have a cinema called "Movie Center". After checking their request, I started to investigate what we can get from them&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  Investigation 🕵️
&lt;/h2&gt;

&lt;p&gt;After checking their request I found out that I can use that information for the Twitter bot.&lt;/p&gt;

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

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

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

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

&lt;p&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  Creating the app 👨‍💻
&lt;/h2&gt;

&lt;p&gt;Let’s start by creating our Phoenix app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix phx.new movies_uy
&lt;span class="nb"&gt;cd &lt;/span&gt;movies_uy
mix ecto.create

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

&lt;/div&gt;



&lt;p&gt;Now Im going to add the following dependencies that are needed for the bot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# mix.exs&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:finch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.13"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:oauther&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.1"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:extwitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.12"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:oban&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 2.13"&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;ul&gt;
&lt;li&gt;Finch for doing request to the "Movie Center" API.&lt;/li&gt;
&lt;li&gt;ExTwitter it's a Twitter Client for using Twitter API&lt;/li&gt;
&lt;li&gt;Oban for creating jobs that run whenever we want (in our case once a day)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After adding this don't forget to run &lt;code&gt;mix deps.get&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;




&lt;h3&gt;
  
  
  Config Finch
&lt;/h3&gt;

&lt;p&gt;Let’s configure Finch by adding this, note that you can follow this from the Finch repo too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/movies_uy/application.ex&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;children&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="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Finch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;MoviesUyFinch&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; &lt;/p&gt;




&lt;h3&gt;
  
  
  Config ExTwitter 🧵
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/config.exs&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:extwitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:oauth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="ss"&gt;consumer_key:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TWITTER_CONSUMER_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;consumer_secret:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TWITTER_CONSUMER_SECRET"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;access_token:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TWITTER_ACCESS_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;access_token_secret:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TWITTER_ACCESS_TOKEN_SECRET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;








&lt;h3&gt;
  
  
  Getting Movies 🎬
&lt;/h3&gt;

&lt;p&gt;Let's add the following code that will search for all the movies from the Movie Center API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/movies_uy/movie_center.ex&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MoviesUy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MovieCenter&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;require&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;fetch_movies&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;movie_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://api.movie.com.uy/api/billboard/cinema/weekly?nextReleases=false"&lt;/span&gt;

    &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Finch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;movie_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Finch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MoviesUyFinch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Finch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"items"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;Jason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

      &lt;span class="n"&gt;movies&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"urlSlug"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - https://www.movie.com.uy/movie/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="si"&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;slug&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;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="s2"&gt;"Error!"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can also check if this is working correctly by running the following line on your iex &lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;iex&amp;gt; MoviesUy.MovieCenter.fetch_movies &lt;span class="c"&gt;# this should show all the movies from Movie center API&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;






&lt;h3&gt;
  
  
  Using ExTwitter 🧵
&lt;/h3&gt;

&lt;p&gt;Now is time to build the messages and post them on Twitter using ExTwitter.&lt;/p&gt;

&lt;p&gt;What Im going to do is create a tweet that contains the current date, and the comments of this twitter will be the movies with their current url on Movie Center.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/movies_uy/movie_center.ex&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MoviesUy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MovieCenter&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;require&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;fetch_movies&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;movie_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://api.movie.com.uy/api/billboard/cinema/weekly?nextReleases=false"&lt;/span&gt;

    &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Finch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;movie_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Finch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MoviesUyFinch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Finch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"items"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;Jason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;ExTwitter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;tweet_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;post_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;movies&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;post_thread_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tweet_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;post_thread_message&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"urlSlug"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt; &lt;span class="n"&gt;tweet_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - https://www.movie.com.uy/movie/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="si"&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;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;ExTwitter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;in_reply_to_status_id:&lt;/span&gt; &lt;span class="n"&gt;tweet_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;post_message&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;day:&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;month:&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;year:&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_today&lt;/span&gt;

    &lt;span class="s2"&gt;"Cartelera de Movie Center del &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="si"&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;month&lt;/span&gt;&lt;span class="si"&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;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;ExTwitter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can run this using the same function as before and we should be able to see that is posting correctly on Twitter.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://i.giphy.com/media/K1YAcmDvKNj0IJF7pF/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/K1YAcmDvKNj0IJF7pF/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;




&lt;h3&gt;
  
  
  Config Oban 📅
&lt;/h3&gt;

&lt;p&gt;It’s time to use Oban, this will allow us to create a worker that runs our code whenever we want, in our case once a day! Lets config Oban (you can also read the docs).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix ecto.gen.migration add_oban_jobs_table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open the generated migration and update it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MoviesUy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migrations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AddObanJobsTable&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migrations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version:&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# We specify `version: 1` in `down`, ensuring that we'll roll all the way back down if&lt;/span&gt;
  &lt;span class="c1"&gt;# necessary, regardless of which version we've migrated `up` to.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migrations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally lets run this&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Lets add this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;#config/config.exs&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:movies_uy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;repo:&lt;/span&gt; &lt;span class="no"&gt;MoviesUy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;plugins:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Pruner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Cron&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;crontab:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"@daily"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MoviesUy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DailyWorker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_attempts:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;]}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;queues:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/my_app/application.ex&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;children&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="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch_env!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:movies_uy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Oban&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/movies_uy/workers/daily_worker.ex&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MoviesUy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DailyWorker&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;queue:&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;Oban&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;MoviesUy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MovieCenter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch_movies&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thats it! you can see this Twitter bot working visiting: &lt;a href="https://twitter.com/movies_uy" rel="noopener noreferrer"&gt;https://twitter.com/movies_uy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you can also create just a mix app and this guide will work too. I used &lt;code&gt;phx&lt;/code&gt; because Im planning to do another thing in the future with it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  Things we used here:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/sneako/finch" rel="noopener noreferrer"&gt;https://github.com/sneako/finch&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/parroty/extwitter" rel="noopener noreferrer"&gt;https://github.com/parroty/extwitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/sorentwo/oban" rel="noopener noreferrer"&gt;https://github.com/sorentwo/oban&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Visit the bot:
&lt;/h2&gt;

&lt;p&gt;Twitter bot: &lt;a href="https://twitter.com/movies_uy" rel="noopener noreferrer"&gt;https://twitter.com/movies_uy&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The code:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/kexposito/movies-uy" rel="noopener noreferrer"&gt;https://github.com/kexposito/movies-uy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>uruguay</category>
      <category>movies</category>
    </item>
    <item>
      <title>How to add a dump file to our Phoenix app</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Fri, 16 Sep 2022 14:06:07 +0000</pubDate>
      <link>https://dev.to/kexposito/how-to-add-a-dump-file-to-our-phoenix-app-4jmf</link>
      <guid>https://dev.to/kexposito/how-to-add-a-dump-file-to-our-phoenix-app-4jmf</guid>
      <description>&lt;p&gt;Working as developers, sometimes we need to migrate an existing app from one language to other, or even load data from Staging or Prod locally. So this guide shows how we can do that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating dump files
&lt;/h3&gt;

&lt;p&gt;If you don’t have any dump file for testing purposes you can generate one from an existing database&lt;/p&gt;

&lt;p&gt;Of course you can create just one file that have the schemas and inserts,I prefer to have them in different files. You can learn more about all psql commands on &lt;a href="https://www.postgresql.org/docs/current/app-pgdump.html"&gt;https://www.postgresql.org/docs/current/app-pgdump.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create schema dump file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pg_dump &lt;span class="nt"&gt;--schema-only&lt;/span&gt; &lt;span class="nt"&gt;--file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"schema_dump.sql"&lt;/span&gt; &amp;lt;database_name&amp;gt;
&lt;span class="c"&gt;# or even shorter&lt;/span&gt;
pg_dump &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"schema_dump.sql"&lt;/span&gt; &amp;lt;database_name&amp;gt;

&lt;span class="c"&gt;# --file=file&lt;/span&gt;
&lt;span class="c"&gt;# Send output to the specified file.&lt;/span&gt;

&lt;span class="c"&gt;# --schema-only&lt;/span&gt;
&lt;span class="c"&gt;# Dump only the object definitions (schema), not data.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create inserts dump file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pg_dump &lt;span class="nt"&gt;--data-only&lt;/span&gt; &lt;span class="nt"&gt;--file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"insert_dump.sql"&lt;/span&gt; &amp;lt;database_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Applying data to our new databse
&lt;/h3&gt;

&lt;p&gt;First of all you should create the database for you application:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you already have the dump file, you can run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix ecto.load &lt;span class="nt"&gt;-d&lt;/span&gt; &amp;lt;path_of_dumps&amp;gt;/schema_dump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the tables from the dump to our Phoenix app&lt;/p&gt;

&lt;p&gt;If we have a data that we also want to add, we can use the same command in order to add the data to our app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix ecto.load &lt;span class="nt"&gt;-d&lt;/span&gt; &amp;lt;path_of_dumps&amp;gt;/inserts_dump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we are ready to rock!&lt;/p&gt;

&lt;p&gt;Now you should be able to generate migrations and run them on top of this!&lt;/p&gt;

&lt;p&gt;Things we used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/ecto_sql/Mix.Tasks.Ecto.Load.html"&gt;https://hexdocs.pm/ecto_sql/Mix.Tasks.Ecto.Load.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/current/app-pgdump.html"&gt;https://www.postgresql.org/docs/current/app-pgdump.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>My Nvim setup process</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Fri, 18 Feb 2022 01:00:26 +0000</pubDate>
      <link>https://dev.to/kexposito/my-nvim-setup-process-5ffp</link>
      <guid>https://dev.to/kexposito/my-nvim-setup-process-5ffp</guid>
      <description>&lt;p&gt;Some of us have some special configurations and guides we like to follow for some tools like bspwm, sxhkd, polybar, terminal, etc. And here is mine for Vim, which I want to share with you.&lt;/p&gt;

&lt;p&gt;⚠️ Make sure you have git installed, because one of our vim plugins will need that in order to work correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Download Nvim
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://github.com/neovim/neovim/releases" rel="noopener noreferrer"&gt;https://github.com/neovim/neovim/releases&lt;/a&gt; and select the latest version from nvim and check &lt;code&gt;Assets&lt;/code&gt; and download &lt;code&gt;nvim.appimage&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Nvim
&lt;/h2&gt;

&lt;p&gt;Open a terminal and copy the code below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/Downloads
chmod u+x nvim.appimage &amp;amp;&amp;amp; ./nvim.appimage

sudo mv nvim.appimage /usr/local/bin
sudo chmod +x /usr/local/bin/nvim.appimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case that I want to rename it i will run the following command (you can also declare an alias for it).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mv /usr/local/bin/nvim.appimage /usr/local/bin/vim 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! we have Nvim installed and ready to go, but lets add some pretty configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install VimPlug
&lt;/h3&gt;

&lt;p&gt;You can install VimPlug by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \
   https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and create the following directory:&lt;br&gt;
&lt;code&gt;mkdir ~/.config/nvim/&lt;/code&gt;&lt;br&gt;
&lt;code&gt;mkdir ~/.config/nvim/plugged&lt;/code&gt; (I will use this folder in our init.config)&lt;/p&gt;

&lt;p&gt;If you are having any issue with this please follow the instructions here: &lt;a href="https://github.com/junegunn/vim-plug#unix-linux" rel="noopener noreferrer"&gt;https://github.com/junegunn/vim-plug#unix-linux&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Init.vim
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/VDXi0uEieSFC856ado/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/VDXi0uEieSFC856ado/giphy.gif" alt="superpower"&gt;&lt;/a&gt;&lt;br&gt;
You shoud create the following file:&lt;br&gt;
&lt;code&gt;vim ~/.config/nvim/init.vim&lt;/code&gt; and fill it with your configuration.&lt;br&gt;
Here is my init.vim, but I &lt;strong&gt;strongly&lt;/strong&gt; suggest to use the things that you like and you feel comfortable with. And just adapt this guide to your preferences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/kexposito/6a22cf04e83402c64b77c1434e63bef5" rel="noopener noreferrer"&gt;https://gist.github.com/kexposito/6a22cf04e83402c64b77c1434e63bef5&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing addons
&lt;/h2&gt;

&lt;p&gt;Now that we copy, or added some Plugs we are ready to&lt;br&gt;
open vim and run &lt;code&gt;:PlugInstall&lt;/code&gt;. (In case you already have addons)&lt;br&gt;
I will create a guide for the most used addons by myself so keep tune.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding colorscheme to our Nvim
&lt;/h3&gt;

&lt;p&gt;Let's create a &lt;strong&gt;color&lt;/strong&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir ~/.config/nvim/colors&lt;/code&gt;&lt;br&gt;
And create a file named &lt;code&gt;railscasts.vim&lt;/code&gt;&lt;br&gt;
&lt;code&gt;vim ~/.config/nvim/colors/railscasts.vim&lt;/code&gt;&lt;br&gt;
and paste the following code &lt;a href="https://gist.github.com/kexposito/16ed1d356d5bdcdc6709573a9e61e9b8" rel="noopener noreferrer"&gt;https://gist.github.com/kexposito/16ed1d356d5bdcdc6709573a9e61e9b8&lt;/a&gt;&lt;br&gt;
(This railscasts.vim file was taken from &lt;a href="https://github.com/cedarcode/cedarvim" rel="noopener noreferrer"&gt;https://github.com/cedarcode/cedarvim&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" To use for gvim:&lt;/span&gt;
&lt;span class="c"&gt;" 1: install this file as ~/.vim/colors/railscasts.vim&lt;/span&gt;
&lt;span class="c"&gt;" 2: put "colorscheme railscasts" in your .gvimrc&lt;/span&gt;
&lt;span class="c"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;" If you are using Ubuntu, you can get the benefit of this in your&lt;/span&gt;
&lt;span class="c"&gt;" terminals using ordinary vim by taking the following steps:&lt;/span&gt;
&lt;span class="c"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;" 1: sudo apt-get install ncurses-term&lt;/span&gt;
&lt;span class="c"&gt;" 2: put the following in your .vimrc&lt;/span&gt;
&lt;span class="c"&gt;"     if $COLORTERM == 'gnome-terminal'&lt;/span&gt;
&lt;span class="c"&gt;"         set term=gnome-256color&lt;/span&gt;
&lt;span class="c"&gt;"         colorscheme railscasts&lt;/span&gt;
&lt;span class="c"&gt;"     else&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following the guide proposed in cedarvim, after this make sure to install &lt;code&gt;ncurses-term&lt;/code&gt; by running &lt;code&gt;sudo apt-get install ncurses-term&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure terminal to have a good looking
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/MURsKMKVsVgXu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/MURsKMKVsVgXu/giphy.gif" alt="cool"&gt;&lt;/a&gt;&lt;br&gt;
Let's start by changing the terminal theme to &lt;em&gt;solirized&lt;/em&gt; one 😎&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open gnome terminal&lt;/li&gt;
&lt;li&gt;Right click in terminal&lt;/li&gt;
&lt;li&gt;Preferences&lt;/li&gt;
&lt;li&gt;Unnamed&lt;/li&gt;
&lt;li&gt;Colors&lt;/li&gt;
&lt;li&gt;Unselect "use colors from system themes" and select "Solarized Dark". Another cool option would be "Gnome Dark"&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h2&gt;
  
  
  Extra - Add custom fonts
&lt;/h2&gt;

&lt;p&gt;Add Mononoki font to Ubuntu&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://www.nerdfonts.com/font-downloads" rel="noopener noreferrer"&gt;https://www.nerdfonts.com/font-downloads&lt;/a&gt; and search for "Mononoki Nerd Font" (here is a preview of it &lt;a href="https://www.programmingfonts.org/#mononoki" rel="noopener noreferrer"&gt;https://www.programmingfonts.org/#mononoki&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Download&lt;/li&gt;
&lt;li&gt;Open a terminal and run:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir /usr/local/share/fonts/Mononoki
cp ~/Downloads/Mononoki.zip /usr/local/share/fonts/Mononoki
unzip /usr/local/share/fonts/Mononoki/Mononoki.zip
rm /usr/local/share/fonts/Mononoki/Mononoki.zip
sudo fc-cache -fv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;If you had any issue following these steps here is a guide for you too &lt;a href="https://www.addictivetips.com/ubuntu-linux-tips/ubuntu-install-fonts-guide/" rel="noopener noreferrer"&gt;https://www.addictivetips.com/ubuntu-linux-tips/ubuntu-install-fonts-guide/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now you should be able to select it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open gnome terminal&lt;/li&gt;
&lt;li&gt;Right click in terminal&lt;/li&gt;
&lt;li&gt;Preferences&lt;/li&gt;
&lt;li&gt;Unnamed&lt;/li&gt;
&lt;li&gt;Select custom font -&amp;gt; mononoki Nerd Font Mono&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have permissions issues use &lt;code&gt;sudo&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📸 Screenshots 📸
&lt;/h2&gt;

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

&lt;p&gt;If you have any special config file or keymapping that you can't work without it please share with us!&lt;/p&gt;

</description>
      <category>vim</category>
      <category>nvim</category>
      <category>ubuntu</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Connecting Ember.js with Phoenix</title>
      <dc:creator>Kevin Expósito</dc:creator>
      <pubDate>Wed, 02 Jun 2021 13:58:33 +0000</pubDate>
      <link>https://dev.to/kexposito/connecting-ember-js-with-phoenix-20k5</link>
      <guid>https://dev.to/kexposito/connecting-ember-js-with-phoenix-20k5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The aim of this article is not only to show how to connect a backend application using Phoenix and a frontend application using Ember, but also to know all the different issues that may be encountered when trying to connect any frontend or backend application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Versions used in this guide:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Elixir: 1.11.3
Erlang/OTP: 21
Phoenix: 1.5.7

Node: 12.13.0
Ember CLI: 3.24.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Creating Phoenix backend
&lt;/h1&gt;

&lt;p&gt;Let's start by creating our project in Phoenix by running the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix phx.new pizza_corner_api
(...)
$ cd pizza_corner_api
$ mix ecto.create
$ iex -S mix phx.server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, let's create a migration in our application:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix phx.gen.schema Api.Pizza pizzas name:string description:text image:string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will generate the following files:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now, we are going to apply the migration by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;


&lt;p&gt;Nice! we have the Pizza table created, let's add some seeds:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
After this, run:&lt;br&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix run priv/repo/seeds.exs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Returning JSON API Responses with JaSerializer
&lt;/h2&gt;

&lt;p&gt;Now we are almost ready to create the PizzaController and router, but before doing that, let's think about what we are doing. We are building the frontend in Ember and the backend in Phoenix. These technologies must communicate with each other. To do this we are going to use JSON API. This means that Phoenix and Ember apps must send and receive JSONAPI responses.&lt;/p&gt;

&lt;p&gt;To do this in Phoenix we are going to use JaSerializer (&lt;a href="https://github.com/vt-elixir/ja_serializer" rel="noopener noreferrer"&gt;https://github.com/vt-elixir/ja_serializer&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing JaSerializer
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# mix.exs&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ja_serializer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.16.0"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:poison&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 3.1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mix deps.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config.exs&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:phoenix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:format_encoders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"json-api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Poison&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:mime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
  &lt;span class="s2"&gt;"application/vnd.api+json"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"json-api"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And then:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix deps.clean mime --build
$ mix deps.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# router.ex&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:accepts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"json-api"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;JaSerializer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ContentTypeNegotiation&lt;/span&gt;
  &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;JaSerializer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Deserializer&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, we are going to create the Pizza View and Controller:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Don't forget to add the endpoint to the router!&lt;br&gt;
&lt;/p&gt;

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

  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/pizzas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PizzaController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Creating the Ember frontend
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ember new pizza_corner --no-welcome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Adding the Pizza Model
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Now, lets run the following code to see if everything is working fine:&lt;br&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ember s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and check it &lt;a href="http://localhost:4200" rel="noopener noreferrer"&gt;http://localhost:4200&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  What is happening?
&lt;/h1&gt;

&lt;p&gt;If we open the console, we will see something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetl11dsomjjh6s6s0dg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetl11dsomjjh6s6s0dg3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
What does this mean? By default Ember will request the same URL it is running on, so we must specify that we want to hit our Phoenix backend. To do this, we have to override the adapter as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;host&lt;/em&gt;&lt;/strong&gt; is the url that we want to hit, and &lt;strong&gt;&lt;em&gt;namespace&lt;/em&gt;&lt;/strong&gt; is the path after the host. This is because, in the Phoenix router we specified that &lt;code&gt;pizzas&lt;/code&gt; are inside &lt;code&gt;api&lt;/code&gt; scope. By doing this and thanks to Ember JSONAPIAdapter, &lt;code&gt;store.findAll('pizza')&lt;/code&gt; will hit &lt;code&gt;http://localhost:4000/api/pizzas&lt;/code&gt; . To see more about this you can see: &lt;a href="https://api.emberjs.com/ember-data/release/classes/JSONAPIAdapter" rel="noopener noreferrer"&gt;https://api.emberjs.com/ember-data/release/classes/JSONAPIAdapter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;app/serializers/application.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now, let's try again, hopefully we will see some magic.&lt;br&gt;
And no magic happens, So.. lets see the inspector again 😡&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finum8u7rtjqa35gyd8sf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finum8u7rtjqa35gyd8sf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  We are having a CORS issue here. Why does this happens?
&lt;/h2&gt;

&lt;p&gt;This happens because of security. CORS doesn't allow communication between our Ember web app (&lt;a href="http://localhost:4200" rel="noopener noreferrer"&gt;http://localhost:4200&lt;/a&gt;) and our Phoenix api (&lt;a href="http://localhost:4000" rel="noopener noreferrer"&gt;http://localhost:4000&lt;/a&gt;) because they are not from the same path and this is not safe.&lt;/p&gt;
&lt;h2&gt;
  
  
  What can we do to fix this?
&lt;/h2&gt;

&lt;p&gt;In order to fix this, we should tell our Phoenix API to accept incoming requests from Ember. To do this, we will use CORS Plug &lt;a href="https://github.com/mschae/cors_plug" rel="noopener noreferrer"&gt;https://github.com/mschae/cors_plug&lt;/a&gt;,  this plugin will allow us to configure that.&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing CORS Plug
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# mix.exs&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:cors_plug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 2.0"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix deps.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;#lib/pizza_corner_api_web/endpoint.ex&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;PizzaCornerApiWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Endpoint&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Phoenix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:pizza_corner_api&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;CORSPlug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;origin:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:4200"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;- Add this&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;PizzaCornerApiWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Router&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after this, restart the server:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now visit &lt;a href="http://localhost:4200" rel="noopener noreferrer"&gt;http://localhost:4200&lt;/a&gt; one more time. You will see the pizzas from our backend being rendered! 🎉🎉🍕&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/phoenix/up_and_running.html" rel="noopener noreferrer"&gt;https://hexdocs.pm/phoenix/up_and_running.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Schema.html" rel="noopener noreferrer"&gt;https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Schema.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/phoenix/routing.html" rel="noopener noreferrer"&gt;https://hexdocs.pm/phoenix/routing.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ember Documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cli.emberjs.com/release/basic-use/cli-commands/" rel="noopener noreferrer"&gt;https://cli.emberjs.com/release/basic-use/cli-commands/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://guides.emberjs.com/release/getting-started/quick-start/" rel="noopener noreferrer"&gt;https://guides.emberjs.com/release/getting-started/quick-start/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://guides.emberjs.com/release/routing/specifying-a-routes-model/" rel="noopener noreferrer"&gt;https://guides.emberjs.com/release/routing/specifying-a-routes-model/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://guides.emberjs.com/release/models/#toc_models" rel="noopener noreferrer"&gt;https://guides.emberjs.com/release/models/#toc_models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://guides.emberjs.com/release/models/customizing-adapters/" rel="noopener noreferrer"&gt;https://guides.emberjs.com/release/models/customizing-adapters/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.emberjs.com/ember-data/release/classes/JSONAPIAdapter" rel="noopener noreferrer"&gt;https://api.emberjs.com/ember-data/release/classes/JSONAPIAdapter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things we used here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JaSerializer (&lt;a href="https://github.com/vt-elixir/ja_serializer" rel="noopener noreferrer"&gt;https://github.com/vt-elixir/ja_serializer&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Poison (&lt;a href="https://github.com/devinus/poison" rel="noopener noreferrer"&gt;https://github.com/devinus/poison&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Cors Plug (&lt;a href="https://github.com/mschae/cors_plug" rel="noopener noreferrer"&gt;https://github.com/mschae/cors_plug&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elixir</category>
      <category>ember</category>
      <category>phoenix</category>
    </item>
  </channel>
</rss>
