<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Marcelo Zárate]]></title><description><![CDATA[Marcelo Zárate]]></description><link>https://marcelozarate.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 08:44:21 GMT</lastBuildDate><atom:link href="https://marcelozarate.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Learning together challenge: Alpine.js and Fake API (first time use)]]></title><description><![CDATA[Good day, fellow reader. 
My name is Marcelo Zarate and on my first post I stated that one of the reasons I've started this blog is to learn. So today, instead of the classic blog entry with very neat and detailed explanations of what to do here, and...]]></description><link>https://marcelozarate.com/learning-together-challenge-alpinejs-and-fake-api-first-time-use</link><guid isPermaLink="true">https://marcelozarate.com/learning-together-challenge-alpinejs-and-fake-api-first-time-use</guid><category><![CDATA[alpinejs]]></category><category><![CDATA[APIs]]></category><category><![CDATA[#learning-in-public]]></category><category><![CDATA[Alpine]]></category><category><![CDATA[#fakeapi]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Thu, 21 Jul 2022 16:44:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658399568959/D7yLja3Sp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader. </p>
<p>My name is <a target="_blank" href="https://marcelozarate.com/">Marcelo Zarate</a> and on my <a target="_blank" href="https://marcelozarate.com/the-start-of-a-writing-journey">first post</a> I stated that one of the reasons I've started this blog is to learn. So today, instead of the classic blog entry with very neat and detailed explanations of what to do here, and there, we are going to learn together. Or, if you already know the subject, you are going to watch and enjoy the experiment.
I'm going to try learning Alpine.js alongside you. I have some experience with frontend frameworks, some good memories with jQuery. After reading <a target="_blank" href="https://2021.stateofjs.com/en-US/libraries/front-end-frameworks">state of Js 2021</a> I've decided to give Alpine a go, at least for small projects.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658413096166/vOaaYcx9n.webp" alt="confused.webp" class="image--center mx-auto" /></p>
<h1 id="heading-the-mission">The mission</h1>
<p>Let's build a simple app just by using</p>
<ul>
<li>Alpine.js</li>
<li><a target="_blank" href="https://jsonplaceholder.typicode.com/">JSON Placeholder Fake API</a></li>
</ul>
<h1 id="heading-the-conditions">The conditions</h1>
<p>I've never used any of the above. If you also haven't, then this post is probably be more interesting for you.
Conditions actually are:</p>
<ul>
<li>No cheating. I will start from Alpine.js documentation, and try to work it out from there.</li>
<li>No googling. Or at least, being honest if I get stuck and I need to search something.</li>
</ul>
<h1 id="heading-lets-start">Let's start</h1>
<h2 id="heading-introduction">Introduction</h2>
<p>Ok, first we go to <a target="_blank" href="https://alpinejs.dev/">Alpine.js homepage</a> and the first screen is an example of usage</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"//unpkg.com/alpinejs"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ open: false }"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"open = true"</span>&gt;</span>Expand<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-show</span>=<span class="hljs-string">"open"</span>&gt;</span>
      Content...
    <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>We just try it out locally, and it works!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652914576589/BBkq8Z1P-.gif" alt="example.gif" class="image--center mx-auto" /></p>
<center>
Image 1: Example from documentation in action
</center>

<p>So, deducting from the example it seems that x-show attachs some visibility attribute to the block. x-data defines the (data/model?) and @click really looks like Vue v-on, triggering the assignment open = true when the button is clicked.</p>
<h2 id="heading-fetching-data">Fetching data</h2>
<p>Ok, from the homepage example, we are going to preserve only the "importing"</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"//unpkg.com/alpinejs"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>We need to fetch the data from the Fake API, following its <a target="_blank" href="https://jsonplaceholder.typicode.com/guide/">guide</a></p>
<blockquote>
<p>I found this service after reading Roger Camargo's blog article <a target="_blank" href="https://huogerac.hashnode.dev/3-ways-to-mock-an-api-in-javascript-or-where-those-can-help-you">3 ways to mock an API in JAvascript</a>. Great article if you have any interest in that topic!</p>
</blockquote>
<pre><code class="lang-js">fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts'</span>)
  .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> response.json())
  .then(<span class="hljs-function">(<span class="hljs-params">json</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(json));
</code></pre>
<p>So, it seems that our main div is going to be</p>
<pre><code class="lang-js">&lt;div x-data=<span class="hljs-string">"{ users: [] }"</span>
    x-init=<span class="hljs-string">"fetch('https://jsonplaceholder.typicode.com/users')
    .then(response =&gt; response.json())
    .then(data =&gt; users = data)"</span>&gt;
&lt;/div&gt;
</code></pre>
<p>Now, since we are populating x-data with the information from the fetch, and users is an array, we need a frontend sintax to loop through that array, looking down in alpine documentation we can find the x-for directive that states "Repeat a block of HTML based on a data set". Fits perfectly.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">x-for</span>=<span class="hljs-string">"user in users"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"user.name"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"user.username"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> - <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"user.email"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652914671649/taBEqCoBI.png" alt="only-names-showing-up.png" class="image--center mx-auto" /></p>
<center>
Image 2: Only names are showing up
</center>

<p>Seems to kinda work? I suspect something here, but we better go to the <a target="_blank" href="https://alpinejs.dev/directives/for">x-for documenation</a> (remember, I've never used Alpine)</p>
<p>Documentation says:</p>
<blockquote>
<p>There are two rules worth noting about x-for:</p>
<ul>
<li>x-for MUST be declared on a  element</li>
<li>That  element MUST have only one root element</li>
</ul>
</blockquote>
<p>Ok, so confirmed, we need to wrap our tags with one root element. I'll be using a div tag, should be something more meaningful, I don't know if the fragment concept from React is available in Alpine, but let's keep it simple for now:</p>
<pre><code class="lang-js">&lt;template x-<span class="hljs-keyword">for</span>=<span class="hljs-string">"user in users"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"user.name"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"user.username"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> - <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"user.email"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/template&gt;
</code></pre>
<p>And the result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652915626173/PR6KBVLx5.png" alt="list-of-names-and-emails.png" class="image--center mx-auto" /></p>
<h1 id="heading-deleting">Deleting</h1>
<p>Ok, so what if we want to delete one user? Fake API allow us to simulate a delete request, quoting the guide</p>
<pre><code class="lang-js">fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts/1'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'DELETE'</span>,
});
</code></pre>
<p>Then we might need to add a button like this</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"fetch('https://jsonplaceholder.typicode.com/users/'+user.id, {
    method: 'DELETE',
});"</span>&gt;</span>
    Delete user
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<h1 id="heading-editing">Editing</h1>
<p>Well, instead of editing in another page, we want to actually toggle editing in the same page, so we probably need something to hide or display inputs. Quickly scrapping we can see x-show and x-if there, they don't look too much different so we are going with the first one that doesn't use the template tag.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-show</span>=<span class="hljs-string">"open"</span>&gt;</span>
  ...
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>And we will need to populate and probably sync the data, seems that x-model is going to serve us well.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ search: '' }"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"search"</span>&gt;</span>

  Searching for: <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"search"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>So we are thinking of something like (we will allow to edit only the name for now, we could just extend the behaviour for other parameters)</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-show</span>=<span class="hljs-string">"editUser"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"user.name"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>And declaring the boolean editUser in x-data. But that variable  is going to be shared with all users, so, if I program a button to edit some user, all the users are going to show their edit inputs (I tried at first, but didn't liked it). So, we are going to need a way to identify in the frontend WHICH user are we currently editing.</p>
<p>We will change the initial x-data</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- BEFORE --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ users: [] }"</span> <span class="hljs-attr">...</span>&gt;</span>
<span class="hljs-comment">&lt;!-- AFTER --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ users: [], editingUser: 0}"</span> <span class="hljs-attr">...</span>&gt;</span>
</code></pre>
<p>and we will set editingUser with the id of the current user to edit.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"editingUser = user.id;"</span>&gt;</span>Edit Records<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>Now, in the x-show, if the user.id matches the editingUser, show the edit box</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-show</span>=<span class="hljs-string">"user.id === editingUser"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"user.name"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Now, inside that block, we will also need some buttons to actually save the edit, and another one to cancel the edition</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"console.log('saving user: '+user.id);"</span>&gt;</span>Save<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"editingUser = null;"</span>&gt;</span>Cancel<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>purists will come after us for that editingUser = null</p>
<p>Now, an extra, hitting on cancel would be nice to make the value as the original one, but since x-model syncs the input with the actual value, we will need to store the original name in case the user hits cancel and wants it back</p>
<p>So our div becomes</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ users: [], editingUser: 0, originalName: ''}"</span> <span class="hljs-attr">...</span>&gt;</span>
</code></pre>
<p>And the cancel button</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"editingUser = null; user.name = originalName;"</span>&gt;</span>Cancel<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<h1 id="heading-updating">Updating</h1>
<p>Here, we have two options, to send a PUT request or PATCH request. We are going with the latter</p>
<p>According to the guide on JSON Placeholder:</p>
<pre><code class="lang-js">fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts/1'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'PATCH'</span>,
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    <span class="hljs-attr">title</span>: <span class="hljs-string">'foo'</span>,
  }),
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-type'</span>: <span class="hljs-string">'application/json; charset=UTF-8'</span>,
  },
})
  .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> response.json())
  .then(<span class="hljs-function">(<span class="hljs-params">json</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(json));
</code></pre>
<p>Now our "save" button on editing changes from this</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"console.log('saving user: '+user.id);"</span>&gt;</span>Save<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"editingUser = null;"</span>&gt;</span>Cancel<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>to this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"fetch('https://jsonplaceholder.typicode.com/posts/1', {
    method: 'PATCH',
    body: JSON.stringify({
      name: 'Test',
    }),
    headers: {
      'Content-type': 'application/json; charset=UTF-8',
    },
    })
    .then((response) =&gt; response.json())
    .then((json) =&gt; console.log(json));"</span>&gt;</span>
    Save
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>It works, well, kind of. If we inspect the network tab in developer tools we can see that the endpoint is called correctly, but, in the case of creating/updating/deleting, according to the <a target="_blank" href="https://jsonplaceholder.typicode.com/guide/">JSON Placeholder guide</a>:</p>
<blockquote>
<p><strong>Important:</strong> resource will not be really updated on the server but it will be faked as if.</p>
</blockquote>
<h1 id="heading-finishing-touches">Finishing touches</h1>
<p>So well. This is our final "functional" CRUD with Alpine.js and JSON Placeholder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654638467212/xK78T9gNm.png" alt="no-style-final-result.png" class="image--center mx-auto" /></p>
<p>Looks pretty boring. Let's spend no more than 5 minutes with style touches using <a target="_blank" href="https://tailwindcss.com/">Tailwind CSS</a> classes and <a target="_blank" href="https://daisyui.com/">DaisyUI</a> default themes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654706629850/TE5A5TwIk.png" alt="styled-final-result.png" class="image--center mx-auto" /></p>
<h1 id="heading-the-code">The code</h1>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="7630723d2adea307ecb83e24bb5312ed"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/marcelozarate/7630723d2adea307ecb83e24bb5312ed" class="embed-card">https://gist.github.com/marcelozarate/7630723d2adea307ecb83e24bb5312ed</a></div><p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[Convert numbers with imperial or european separators]]></title><description><![CDATA[Good day, fellow reader. 
Have you ever been in a position where you have not to validate a strict format, but to try to get the number provided even if it has spaces or different separator? 
Chances are, if you work in a country where the dot is use...]]></description><link>https://marcelozarate.com/convert-numbers-with-imperial-or-european-separators</link><guid isPermaLink="true">https://marcelozarate.com/convert-numbers-with-imperial-or-european-separators</guid><category><![CDATA[python beginner]]></category><category><![CDATA[pytest]]></category><category><![CDATA[Math]]></category><category><![CDATA[automation]]></category><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Tue, 10 May 2022 11:04:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651947017479/LOiGcJKzl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader. </p>
<p><em>Have you ever been in a position where you have not to validate a strict format, but to try to get the number provided even if it has spaces or different separator? </em></p>
<p>Chances are, if you work in a country where the dot is used to distinguish between the integer and decimal part, <em>you probably didn't need to</em>, as most coding languages and computational number representations use this style (e.g.: 123.45, 0.99).</p>
<p>In this article, I'm going to share a bit about this subject and how I overcame these differences with some python code.</p>
<h1 id="heading-numbers-format-imperial-vs-european">Numbers format (Imperial vs European)</h1>
<p>This article by Raluca Cristina Neagu: <a target="_blank" href="https://www.languageediting.com/format-numbers-eu-vs-us/">Number formatting in Europe vs. the US</a> is a piece of gold in a subject. Not only because of the references included, but the way the author describes the subject as a short, clear story. I know I probably got your attention for maybe one extra minute or so. The quote below is for you, then:</p>
<blockquote>
<p>Why are there different number formats? It appears that the comma separator was introduced to avoid confusion with the dot being used as operator, bringing chaos to these days.</p>
<p>So who to blame? Haven't read all the material about it, but it seems that decimal point popularity comes from Napier usage, and decimal comma popularity comes from Leibniz. You probably hate them both if you had the chance to learn from their work.</p>
<p>Ok, so what's the standard, who wins? Well, The International System of Units (SI) calls it a draw. You can use comma, or dot, and it is valid. The real losers here are the separators, they must be a space, or nothing at all. No dots, no commas. 9,999,999.99 is not valid, neither 9.999.999,99 it should be 9 999 999.99 or 9 999 999,99.</p>
</blockquote>
<h1 id="heading-dealing-with-conversion">Dealing with conversion</h1>
<p>This is a tiny list of some of the formats I've found while automatic processing probably a hundred of documents. Numbers are fictional, formats are not.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Provided number</td><td>Converted</td></tr>
</thead>
<tbody>
<tr>
<td>$ 159 195.533</td><td>159195.533</td></tr>
<tr>
<td>$ 155,132,158.0</td><td>155132158.0</td></tr>
<tr>
<td>99,999.99</td><td>99999.99</td></tr>
<tr>
<td>13.194,32</td><td>13194.32</td></tr>
<tr>
<td>$ 20.212,99</td><td>20212.99</td></tr>
</tbody>
</table>
</div><p>You get the idea, so we first need to remove the <code>$</code> and white spaces</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Numbers with no $ and spaces</td></tr>
</thead>
<tbody>
<tr>
<td>159195.533</td></tr>
<tr>
<td>155,132,158.0</td></tr>
<tr>
<td>99,999.99</td></tr>
<tr>
<td>13.194,32</td></tr>
<tr>
<td>20.212,99</td></tr>
</tbody>
</table>
</div><p>Now, only the first one won't raise any errors if we try to parse with python's useful <code>float</code> method. We need to remove the three-digit separators.</p>
<ul>
<li>Imperial format: We remove the <code>,</code> and we are good, as the decimal separator <code>.</code> would match the computational representation.</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Numbers</td><td>Converted</td></tr>
</thead>
<tbody>
<tr>
<td>159195.533</td><td>159195.533</td></tr>
<tr>
<td>155,132,158.0</td><td>155132158.0</td></tr>
<tr>
<td>99,999.99</td><td>99999.99</td></tr>
</tbody>
</table>
</div><ul>
<li>European format: If we remove the <code>,</code> first, we would lose reference of what is the integer, and what is the decimal part. So we need to first remove any <code>.</code> digit separator (step 1), and then, replace the <code>,</code> by a <code>.</code> (step 2)</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Numbers</td><td>Step 1</td><td>Step 2</td></tr>
</thead>
<tbody>
<tr>
<td>13.194,32</td><td>13194,32</td><td>13194.32</td></tr>
<tr>
<td>20.212,99</td><td>20212,99</td><td>20212.99</td></tr>
</tbody>
</table>
</div><p>If you think like a machine, you probably noticed that we can't apply both indistinctly, that we need first to find out if we are dealing with one type of number format or another.</p>
<blockquote>
<p>Don’t do the natural thing, the impulsive thing. - Dale Carnegie </p>
</blockquote>
<p>Well, luckily, Dale Carnegie know nothing about programming, so we're going full impulsive here.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">-1</span>, -len(text), <span class="hljs-number">-1</span>):
        <span class="hljs-keyword">if</span> text[i] == <span class="hljs-string">"."</span> <span class="hljs-keyword">or</span> text[i] == <span class="hljs-string">","</span>:
            foundSeparator = text[i]
            <span class="hljs-keyword">break</span>
</code></pre>
<p>We traverse the number string in reverse order until we find the decimal separator, then, we find our number format. No more questions, your honor.</p>
<h1 id="heading-wheres-the-full-code">Where's the full code?</h1>
<p>I'll leave below the code with one giant warning. <strong>DO NOT RELY ON THIS FOR CRITICAL APPLICATIONS</strong>. Even when I wrote this in a work environment, the outcomes of this algorithm can be somewhat verified, and no lives or jobs depend on the accurateness of it (except, maybe mine).</p>
<p>I added some basic testing as well, so you can check when it fails.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> math
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getNumberWithAnySeparator</span>(<span class="hljs-params">text</span>):</span>
    text = str(text).replace(<span class="hljs-string">" "</span>, <span class="hljs-string">""</span>)
    text = text.replace(<span class="hljs-string">"$"</span>, <span class="hljs-string">""</span>)
    foundSeparator = <span class="hljs-string">""</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">-1</span>, -len(text), <span class="hljs-number">-1</span>):
        <span class="hljs-keyword">if</span> text[i] == <span class="hljs-string">"."</span> <span class="hljs-keyword">or</span> text[i] == <span class="hljs-string">","</span>:
            foundSeparator = text[i]
            <span class="hljs-keyword">break</span>
    <span class="hljs-keyword">if</span> foundSeparator == <span class="hljs-string">"."</span>: <span class="hljs-comment"># Imperial format xxx,xxx.xx</span>
        text = text.replace(<span class="hljs-string">","</span>, <span class="hljs-string">""</span>)
    <span class="hljs-keyword">if</span> foundSeparator == <span class="hljs-string">","</span>: <span class="hljs-comment"># European format xxx.xxx,xx</span>
        text = text.replace(<span class="hljs-string">"."</span>, <span class="hljs-string">""</span>)
        text = text.replace(<span class="hljs-string">","</span>, <span class="hljs-string">"."</span>)
    <span class="hljs-keyword">return</span> tryFloat(text)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tryFloat</span>(<span class="hljs-params">text</span>):</span>
    <span class="hljs-keyword">try</span>:
        auxValue = float(text)
    <span class="hljs-keyword">except</span> ValueError:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> math.isnan(auxValue):
        <span class="hljs-keyword">return</span> auxValue
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

<span class="hljs-keyword">import</span> unittest

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestConversion</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_zero</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Test that 0 converts to 0
        """</span>
        text = <span class="hljs-string">"0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">0</span>)
        text = <span class="hljs-string">"0,0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">0</span>)
        text = <span class="hljs-string">"$0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">0</span>)
        text = <span class="hljs-string">"$ 0,0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">0</span>)
        text = <span class="hljs-string">"-0.0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">0</span>)
        text = <span class="hljs-string">"0000000000000000.0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">0</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_alpha</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Test that alphanumeric converts to None
        """</span>
        text = <span class="hljs-string">"a0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-literal">None</span>)
        text = <span class="hljs-string">"zero"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-literal">None</span>)
        text = <span class="hljs-string">"l2"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-literal">None</span>)
        text = <span class="hljs-string">"OOO"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-literal">None</span>)
        text = <span class="hljs-string">"0z"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-literal">None</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_positive</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Test that some positive numbers convert to their value
        """</span>
        text = <span class="hljs-string">"123"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">123</span>)
        text = <span class="hljs-string">"+99"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">99</span>)
        text = <span class="hljs-string">"$159195.533"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">159195.533</span>)
        text = <span class="hljs-string">"$ 155, 132, 158.0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">155132158</span>)
        text = <span class="hljs-string">"32 913 646"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">32913646</span>)
        text = <span class="hljs-string">"12.529,52"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">12529.52</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_negative</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Test that some negative numbers convert to their value
        """</span>
        text = <span class="hljs-string">"-123"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">-123</span>)
        text = <span class="hljs-string">"-99"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">-99</span>)
        text = <span class="hljs-string">"-$159195.533"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">-159195.533</span>)
        text = <span class="hljs-string">"-$ 155, 132, 158.0"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">-155132158</span>)
        text = <span class="hljs-string">"-32 913 646"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">-32913646</span>)
        text = <span class="hljs-string">"-12.529,52"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">-12529.52</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_mix_cases</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Test cases where there is mix of patterns
        """</span>
        text = <span class="hljs-string">"-123.4124.2,521.2"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-literal">None</span>)
        text = <span class="hljs-string">"-$99,125 242 5"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">-99.1252425</span>)
        text = <span class="hljs-string">",15.9195533"</span>
        result = getNumberWithAnySeparator(text)
        self.assertEqual(result, <span class="hljs-number">15.9195533</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    unittest.main()
</code></pre>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div><p><a target="_blank" href="https://www.freepik.es/vectores/popular">Portrait picture has been designed used "VS" image created by jcomp - www.freepik.es</a></p>
]]></content:encoded></item><item><title><![CDATA[Bottom sticky navigation with TailwindCSS]]></title><description><![CDATA[Good day, fellow reader. Today I want to share with you a simple snippet to achieve something simple, yet so important. Have you ever seen those mobile-like menus at the bottom of some apps? They usually have max 5 items and allow you to quickly, and...]]></description><link>https://marcelozarate.com/bottom-sticky-navigation-with-tailwindcss</link><guid isPermaLink="true">https://marcelozarate.com/bottom-sticky-navigation-with-tailwindcss</guid><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[UX]]></category><category><![CDATA[user experience]]></category><category><![CDATA[CSS]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Mon, 06 Dec 2021 10:51:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638785631010/3R6PnVWkH.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader. Today I want to share with you a simple snippet to achieve something simple, yet so important. Have you ever seen those mobile-like menus at the bottom of some apps? They usually have max 5 items and allow you to quickly, and easily access the main options of some app.</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638625091201/J03Eu-0p5-.png" alt="5uQ0Oo1YwA.png" />
YouTube's bottom navigation
</center>

<p>Are you familiar with <a target="_blank" href="https://tailwindcss.com/docs">TailwindCSS</a>? Let's use it to make a similar one that changes to a traditional sidebar when viewport is bigger</p>
<blockquote>
<p>Don't know TailwindCSS? You probably first want to read <a class="user-mention" href="https://hashnode.com/@dailydevtips">Chris Bongers</a> and <a target="_blank" href="https://h.daily-dev-tips.com/my-honest-opinion-on-tailwind-css">his honest opinion on Tailwind CSS</a> and then head straight to its great <a target="_blank" href="https://tailwindcss.com/docs">documentation</a></p>
</blockquote>
<h1 id="heading-ux-and-motivation">UX and motivation</h1>
<p>A while ago I read this article <a target="_blank" href="https://www.smashingmagazine.com/2016/09/the-thumb-zone-designing-for-mobile-users/">The thumb zone - designing for mobile users</a>, and it brought to me a lot of concerns about UX.
Sometimes we are so used to a particular type of navigation or components, that we don't take the time to ask the following question</p>
<blockquote>
<p>Are we delivering a comfort navigation and a smooth user experience?</p>
</blockquote>
<p>Having this in mind, for my next app (a PWA, actually) I wanted a sticky navigation bar like showed before, but changing to a more classical sidebar type when the viewport was medium or larger. Widescreens are getting wider every day, and this kind of navigation will definitively be ugly and uncomfortable with big resolutions.</p>
<h1 id="heading-approach">Approach</h1>
<p>Tailwind uses a mobile first breakpoint approach, this means every class we use is applied to the minimum size and larger, and every breakpoint we specify will be applied to that one and larger. That means if we try to add CSS for small screens, we usually don't use breakpoints at all.</p>
<p>For example:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden md:block text-xs pt-1"</span>&gt;</span>Add<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
</code></pre>
<p>This will apply the following styles:</p>
<ul>
<li>hidden (<code>display: hidden;</code> - This will not be visible on mobile)</li>
<li>md:block (<code>display:block;</code> - on medium viewport and larger, this will be visible as block)</li>
<li>text-xs (<code>font-size: 0.75rem; line-height: 1rem;</code> - small text on every viewport)</li>
<li>pt-1 (<code>padding-top: 0.25rem;</code> - padding top)</li>
</ul>
<h1 id="heading-coding">Coding</h1>
<p>With JIT mode, Tailwind allows a whole different experience when playing around with designs. But, for this small component, it's just great to use <a target="_blank" href="https://play.tailwindcss.com/lBFqzmWZLh">Tailwind Play</a>.</p>
<h3 id="heading-bad-news">Bad news</h3>
<p>This article is not about how to use the CSS framework, or a <em>how to</em> tutorial, just a simple introduction to the problem and the <em>Why</em>.</p>
<h3 id="heading-good-news">Good news</h3>
<p>Full code is available here, of course you can improve and modify it as you need. Click the HTML button to see the layout change.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/marcelozarate/pen/yLzYpbB">https://codepen.io/marcelozarate/pen/yLzYpbB</a></div>
<div class="hn-embed-widget" id="three-dots-separator"></div><p>That's it! Hope you find it useful. And if not, thanks for reading anyway.</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[Simple alert dialog PyQt]]></title><description><![CDATA[Good day, fellow reader. I was a Qt user long time ago, and I'm not a PyQt expert at all, in fact, when sometimes I find an answer in  PyQt forum my first thought is: "Wow, this people really know their stuff", doing in three lines what probably take...]]></description><link>https://marcelozarate.com/simple-alert-dialog-pyqt</link><guid isPermaLink="true">https://marcelozarate.com/simple-alert-dialog-pyqt</guid><category><![CDATA[python beginner]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[Qt]]></category><category><![CDATA[desktop]]></category><category><![CDATA[Junior developer ]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Sun, 28 Nov 2021 14:30:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638109674230/TXpy3Do-Vt.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader. I was a Qt user long time ago, and I'm not a PyQt expert at all, in fact, when sometimes I find an answer in  <a target="_blank" href="https://forum.qt.io/category/58/qt-for-python">PyQt forum</a> my first thought is: <em>"Wow, this people really know their stuff"</em>, doing in three lines what probably takes me more than ten. But as I fiddle around with PyQt I didn't find a simple, yet customizable way to display annoying alert dialogs to the user. Of course, <a target="_blank" href="https://doc.qt.io/qtforpython/PySide6/QtWidgets/QMessageBox.html?highlight=qmessagebox#the-property-based-api">The property based API</a> handles a lot of the issues I mentioned, but I wanted a one liner solution.</p>
<p>So, this is what we are going to achieve in this article:</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638104168126/UI_h6X_Jm.png" alt="pyqt-like-confirmation-dialog.PNG" />
</center>

<h1 id="heading-objective">Objective</h1>
<p>The goal is to have an option to display an alert in PyQt by issuing</p>
<pre><code class="lang-python">r = showMessageBox(<span class="hljs-string">"Title"</span>, <span class="hljs-string">"All the body text"</span>, <span class="hljs-string">"Question"</span>, <span class="hljs-literal">True</span>, [<span class="hljs-string">"Confirm"</span>, <span class="hljs-string">"No way!"</span>], returnTrue)
</code></pre>
<p>An experienced PyQt user might be wondering <em>why not using the default constructor?</em> Well, although some options are available in it, like setting the buttons text, title and icon, there are limited options regarding customization of the buttons and actions triggered by them. So we are building our own simple PyQt alert dialog.</p>
<h1 id="heading-coding-of-the-pyqt-simple-dialog">Coding of the PyQt simple dialog</h1>
<p>We will define some fixed strings for the available icons ["NoIcon", "Information", "Warning", "Critical", "Question"] and an option to allow for two button or single button mode. We are going to add the possibility for a callback to be executed whenever the uses clicks on OK button.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> PyQt5.QtWidgets <span class="hljs-keyword">import</span> QMessageBox

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">showMessageBox</span>(<span class="hljs-params">title, text, icon=<span class="hljs-string">"NoIcon"</span>, buttons=False, buttonsText=[], callback=None</span>):</span>
    qmb = QMessageBox()
    qmb.setText(text)
    qmb.setWindowTitle(title)
    <span class="hljs-keyword">if</span> icon == <span class="hljs-string">"NoIcon"</span>:
        qmb.setIcon(QMessageBox.NoIcon)
    <span class="hljs-keyword">if</span> icon == <span class="hljs-string">"Information"</span>:
        qmb.setIcon(QMessageBox.Information)
    <span class="hljs-keyword">if</span> icon == <span class="hljs-string">"Warning"</span>:
        qmb.setIcon(QMessageBox.Warning)
    <span class="hljs-keyword">if</span> icon == <span class="hljs-string">"Critical"</span>:
        qmb.setIcon(QMessageBox.Critical)
    <span class="hljs-keyword">if</span> icon == <span class="hljs-string">"Question"</span>:
        qmb.setIcon(QMessageBox.Question)

    <span class="hljs-keyword">if</span> buttons == <span class="hljs-literal">True</span>:
        qmb.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        <span class="hljs-keyword">if</span> len(buttonsText) == <span class="hljs-number">2</span>:
            qmb.button(QMessageBox.Ok).setText(buttonsText[<span class="hljs-number">0</span>])
            qmb.button(QMessageBox.Cancel).setText(buttonsText[<span class="hljs-number">1</span>])
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">if</span> len(buttonsText) == <span class="hljs-number">1</span>:
            qmb.setStandardButtons(QMessageBox.Ok)
            qmb.button(QMessageBox.Ok).setText(buttonsText[<span class="hljs-number">0</span>])

    <span class="hljs-keyword">if</span> qmb.exec() == QMessageBox.Ok:
        <span class="hljs-keyword">if</span> callback:
            <span class="hljs-keyword">return</span> callback()
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
</code></pre>
<h1 id="heading-pyqt-simple-message-box-examples">PyQt simple message box examples</h1>
<h2 id="heading-minimal-alert-box">Minimal alert box</h2>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638104841743/7xWXN0Qbl.png" alt="pyqt-minimal-dialog.PNG" />
</center>

<pre><code class="lang-python">showMessageBox(<span class="hljs-string">"Hey!"</span>, <span class="hljs-string">"How you doin'?"</span>)
</code></pre>
<h2 id="heading-show-error-dialog">Show error dialog</h2>
<p><center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638104928675/pSToX5ds_.png" alt="pyqt-error-dialog-alert.PNG" />
</center></p>
<pre><code class="lang-python">showMessageBox(<span class="hljs-string">"Danger"</span>, <span class="hljs-string">"A critical error just happened"</span>, <span class="hljs-string">"Critical"</span>)
</code></pre>
<h2 id="heading-confirmation-dialog-with-default-buttons">Confirmation dialog with default buttons</h2>
<p><center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638104952687/TfgknhE0H.png" alt="pyqt-confirmation-warning-dialog-message-box.PNG" />
</center></p>
<pre><code class="lang-python">showMessageBox(<span class="hljs-string">"Confirm action"</span>, <span class="hljs-string">"Are you comfortable with this action?"</span>, <span class="hljs-string">"Warning"</span>, <span class="hljs-literal">True</span>)
</code></pre>
<h2 id="heading-confirmation-dialog-with-custom-text-buttons-and-callback">Confirmation dialog with custom text buttons and callback</h2>
<p><center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638105112607/VH_BNghZ_.png" alt="pyqt-custom-message-box-confirmation-callback.PNG" />
</center></p>
<pre><code class="lang-python">returnedStuff = showMessageBox(<span class="hljs-string">"Erasing records"</span>, <span class="hljs-string">"Are you absolutely sure you want to erase the selected records? This operation is not reversible"</span>, <span class="hljs-string">"Warning"</span>, <span class="hljs-literal">True</span>, [<span class="hljs-string">"Yes, erase them"</span>, <span class="hljs-string">"No, don't do it"</span>], eraseSelected)
</code></pre>
<h1 id="heading-full-code">Full code</h1>
<p>In case you just want to try it out, saving this code and running it with <code>python simplealertdialog.py</code></p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="973e409556c9d219fb94c703c9a51289"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/marcelozarate/973e409556c9d219fb94c703c9a51289" class="embed-card">https://gist.github.com/marcelozarate/973e409556c9d219fb94c703c9a51289</a></div><div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="heading-wrapping-up">Wrapping up</h1>
<p>That's it! Simple, yet kind of useful. If you have any suggestions or improvements, I beg you to do it directly in the comments. As I mentioned, I'm almost a trainee in PyQt, but I wanted to share this with you.</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[Creating a dynamic football table]]></title><description><![CDATA[Good day, fellow reader. Football is by far the most popular sport in the world. From the World Cup to regional leagues, this game of low scores, team game, and angry fans, has evolved from the 16th century. Its rules had been changed several times, ...]]></description><link>https://marcelozarate.com/creating-a-dynamic-football-table</link><guid isPermaLink="true">https://marcelozarate.com/creating-a-dynamic-football-table</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[learning]]></category><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[CodePen]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Sun, 07 Nov 2021 23:10:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636326255900/hmpSAG_eb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader. Football is by far the most popular sport in the world. From the World Cup to regional leagues, this game of low scores, team game, and angry fans, has evolved from the 16th century. Its rules had been changed several times, the target audience has spread, and the system of registering and pointing the results from matches has also not been a universal format. To avoid further discussions, we are going to elaborate an automatic positions table.</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636320535659/1vwYL2DDb.webp" alt="clarence-seedorf-running.webp" />
Clarence Seedorf running with the UEFA Champions League trophy
</center>

<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="the-problem">The problem</h1>
<p>For the most part of the world, a game in a league can have <strong>three</strong> outcomes: <strong>win, draw or loss</strong>. A winning team gets 3 points, a losing team gets 0, and a draw awards each team with 1 point.
We will create a simple script using JavaScript that will process a set of matches and will provide as output a nifty table like this</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636238291377/_a5cpg_v4.png" alt="table-example.png" />
</center>

<h3 id="reference">Reference</h3>
<ul>
<li><strong>PL:</strong> Played (matches)</li>
<li><strong>W:</strong> Wins</li>
<li><strong>D:</strong> Draws</li>
<li><strong>L:</strong> Losses</li>
<li><strong>GF:</strong> Goals for</li>
<li><strong>GA:</strong> Goals against</li>
<li><strong>GD:</strong> Goal difference (GF - GA)</li>
<li><strong>P:</strong> Points</li>
</ul>
<h1 id="dynamically-generating-an-html-table">Dynamically generating an HTML table</h1>
<p>With aid from the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement">HTMLTableElement</a> interface, you can follow <a target="_blank" href="https://www.valentinog.com/blog/html-table/">this tutorial</a> from <a target="_blank" href="https://www.valentinog.com">Valentino Gagliardi</a> to grasp an idea of how are we going to modify the DOM dynamically using JavaScript. The main purpose of this article is not <em>how to introduce the data</em>, but<em> how to process and get the needed information for the sports objective</em>.</p>
<h1 id="storing-the-data">Storing the data</h1>
<p>We are going to store the matches in an array of objects. Each object will contain the basic information about the match the simplest way possible</p>
<pre><code class="lang-json">{
  home: <span class="hljs-string">"Home Team Name"</span>,
  away: <span class="hljs-string">"Away Team Name"</span>,
  result: <span class="hljs-string">"1-2"</span>
}
</code></pre>
<h1 id="input-for-the-table">Input for the table</h1>
<p>We will provide the <code>insertTableBody</code> and <code>insertTableHead</code> function with the data, with the following format example.</p>
<pre><code class="lang-json">{NAME: <span class="hljs-string">"River Plate"</span> , PL: <span class="hljs-number">14</span>, W: <span class="hljs-number">7</span>, D: <span class="hljs-number">6</span>, L: <span class="hljs-number">1</span>, GF: <span class="hljs-number">19</span>, GA: <span class="hljs-number">9</span>, GD: <span class="hljs-number">10</span>, P: <span class="hljs-number">27</span>}
</code></pre>
<h1 id="processing-the-input">Processing the input</h1>
<p>So, we must build an array with that information, but how do we convert an array of matches to that?
We are going to use two functions, one to prepare the info and get the participating teams, and another one to calculate the amounts of every property.
The basic pseudocode is</p>
<pre><code>data = []
getDataFromMatches(matches)
    foreach match from matches
        getHomeTeam of match
        getAwayTeam of match
        getHomeGoals of match
        getAwayGoals of match
        if homeTeam is not in data
            add homeTeam to data <span class="hljs-keyword">with</span> <span class="hljs-keyword">empty</span> scores
        <span class="hljs-keyword">if</span> awayTeam <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> <span class="hljs-keyword">data</span>
            <span class="hljs-keyword">add</span> awayTeam <span class="hljs-keyword">to</span> <span class="hljs-keyword">data</span> <span class="hljs-keyword">with</span> <span class="hljs-keyword">empty</span> scores
        processMatchResult(<span class="hljs-keyword">data</span>, homeTeam, awayTeam, homeGoals, awayGoals)
    <span class="hljs-keyword">sort</span> <span class="hljs-keyword">data</span> <span class="hljs-keyword">by</span> points, <span class="hljs-keyword">if</span> equal, <span class="hljs-keyword">by</span> goal <span class="hljs-keyword">difference</span>, <span class="hljs-keyword">if</span> equal, <span class="hljs-keyword">by</span> goals <span class="hljs-keyword">for</span>
</code></pre><p>In the above function, we only get the data from the object, and we initialize the scores with the team names. Then, it's all up to processMatchResult to fill the scores for every match. In this case, the winning, draw, lose, and points depend on the comparison of the scores, but the played, goals for, goals against, and goal difference only represent simple additions.</p>
<pre><code><span class="hljs-attribute">processMatchResult</span>(data, homeTeam, awayTeam, homeGoals, awayGoals)
    <span class="hljs-attribute">homeTeam</span>.PLAYED = homeTeam.PLAYED + <span class="hljs-number">1</span>
    <span class="hljs-attribute">awayTeam</span>.PLAYED = awayTeam.PLAYED + <span class="hljs-number">1</span>
    <span class="hljs-attribute">homeTeam</span>.GF = homeTeam.GF + homeGoals
    <span class="hljs-attribute">awayTeam</span>.GF = awayTeam.GF + awayGoals
    <span class="hljs-attribute">homeTeam</span>.GA = homeTeam.GA + awayGoals
    <span class="hljs-attribute">awayTeam</span>.GA = awayTeam.GA + homeGoals
    <span class="hljs-attribute">homeTeam</span>.GD = homeTeam.GF - homeTeam.GA
    <span class="hljs-attribute">awayTeam</span>.GD = awayTeam.GF - awayTeam.GA

    <span class="hljs-attribute">if</span> homeGoals == awayGoals
        <span class="hljs-attribute">homeTeam</span>.D = homeTeam.D + <span class="hljs-number">1</span>
        <span class="hljs-attribute">homeTeam</span>.P = homeTeam.P + <span class="hljs-number">1</span>
        <span class="hljs-attribute">awayTeam</span>.D = awayTeam.D + <span class="hljs-number">1</span>
        <span class="hljs-attribute">awayTeam</span>.P = awayTeam.P + <span class="hljs-number">1</span>
    <span class="hljs-attribute">if</span> homeGoals &gt; awayGoals
        <span class="hljs-attribute">homeTeam</span>.W = homeTeam.W + <span class="hljs-number">1</span>
        <span class="hljs-attribute">homeTeam</span>.P = homeTeam.P + <span class="hljs-number">3</span>
        <span class="hljs-attribute">awayTeam</span>.L = awayTeam.L + <span class="hljs-number">1</span>
        <span class="hljs-attribute">awayTeam</span>.P = awayTeam.P + <span class="hljs-number">0</span>
    <span class="hljs-attribute">if</span> homeGoals &lt; awayGoals
        <span class="hljs-attribute">awayTeam</span>.W = awayTeam.W + <span class="hljs-number">1</span>
        <span class="hljs-attribute">awayTeam</span>.P = awayTeam.P + <span class="hljs-number">3</span>
        <span class="hljs-attribute">homeTeam</span>.L = homeTeam.L + <span class="hljs-number">1</span>
        <span class="hljs-attribute">homeTeam</span>.P = homeTeam.P + <span class="hljs-number">0</span>
</code></pre><h1 id="javascript-code">JavaScript code</h1>
<p>Now let's just write those functions in JavaScript.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> data = [];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getDataFromMatches</span>(<span class="hljs-params">matches</span>) </span>{    
  matches.forEach(<span class="hljs-function">(<span class="hljs-params">match</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> homeTeam = match.home;
    <span class="hljs-keyword">let</span> awayTeam = match.away;
    <span class="hljs-keyword">let</span> homeGoals = match.result.split(<span class="hljs-string">"-"</span>)[<span class="hljs-number">0</span>];
    <span class="hljs-keyword">let</span> awayGoals = match.result.split(<span class="hljs-string">"-"</span>)[<span class="hljs-number">1</span>];
    <span class="hljs-keyword">let</span> index = data.findIndex(<span class="hljs-function"><span class="hljs-params">team</span> =&gt;</span> team.NAME === homeTeam);
    <span class="hljs-comment">// Home team non-existant in array, let's create it with default scores</span>
    <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) {
      data.push({<span class="hljs-attr">NAME</span>: homeTeam, <span class="hljs-attr">PL</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">W</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">D</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">L</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">GF</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">GA</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">GD</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">P</span>: <span class="hljs-number">0</span>});
    }
    index = data.findIndex(<span class="hljs-function"><span class="hljs-params">team</span> =&gt;</span> team.NAME === awayTeam);
    <span class="hljs-comment">// Away team non-existant in array, let's create it with default scores</span>
    <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) {
      data.push({<span class="hljs-attr">NAME</span>: awayTeam, <span class="hljs-attr">PL</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">W</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">D</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">L</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">GF</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">GA</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">GD</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">P</span>: <span class="hljs-number">0</span>});
    }
    <span class="hljs-comment">// parseInt is neccesary because goals are strings at this point</span>
    processMatchResult(data, homeTeam, awayTeam, <span class="hljs-built_in">parseInt</span>(homeGoals, <span class="hljs-number">10</span>), <span class="hljs-built_in">parseInt</span>(awayGoals, <span class="hljs-number">10</span>));
  });
  <span class="hljs-comment">// data is filled, let's sort it by points, goal difference, goals for.</span>
  data.sort(<span class="hljs-function">(<span class="hljs-params">teamA,teamB</span>)=&gt;</span>(teamA.P - teamB.P || teamA.GD - teamB.GD || teamA.GF - teamB.GF));
  <span class="hljs-comment">// sort gets ascending order, we need to reverse it for a normal league table</span>
  data.reverse();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processMatchResult</span>(<span class="hljs-params">data, homeTeam, awayTeam, homeGoals, awayGoals</span>) </span>{
  <span class="hljs-comment">// We get the reference to each team object</span>
  <span class="hljs-keyword">let</span> indexHT = data.findIndex(<span class="hljs-function"><span class="hljs-params">team</span> =&gt;</span> team.NAME === homeTeam);
  <span class="hljs-keyword">let</span> indexAT = data.findIndex(<span class="hljs-function"><span class="hljs-params">team</span> =&gt;</span> team.NAME === awayTeam);
  <span class="hljs-comment">// Common data (home) - plus one played and registering the goals</span>
  data[indexHT].PL += <span class="hljs-number">1</span>;
  data[indexHT].GF += homeGoals;
  data[indexHT].GA += awayGoals;
  data[indexHT].GD = data[indexHT].GF - data[indexHT].GA;
  <span class="hljs-comment">// Common data (away) - plus one played and registering the goals</span>
  data[indexAT].PL += <span class="hljs-number">1</span>;
  data[indexAT].GF += awayGoals;
  data[indexAT].GA += homeGoals;
  data[indexAT].GD = data[indexAT].GF - data[indexAT].GA;

  <span class="hljs-comment">// Draw</span>
  <span class="hljs-keyword">if</span> (homeGoals === awayGoals) {
    <span class="hljs-comment">// Home team register a draw</span>
    data[indexHT].D += <span class="hljs-number">1</span>;
    data[indexHT].P += <span class="hljs-number">1</span>;
    <span class="hljs-comment">// Away team register a draw</span>
    data[indexAT].D += <span class="hljs-number">1</span>;
    data[indexAT].P += <span class="hljs-number">1</span>;
  }
  <span class="hljs-comment">// Home win</span>
  <span class="hljs-keyword">if</span> (homeGoals &gt; awayGoals) {
    <span class="hljs-comment">// Home team register a win</span>
    data[indexHT].W += <span class="hljs-number">1</span>;
    data[indexHT].P += <span class="hljs-number">3</span>;
    <span class="hljs-comment">// Away team register a loss</span>
    data[indexAT].L += <span class="hljs-number">1</span>;
  }
  <span class="hljs-comment">// Away win</span>
  <span class="hljs-keyword">if</span> (homeGoals &lt; awayGoals) {
    <span class="hljs-comment">// Away team register a win</span>
    data[indexAT].W += <span class="hljs-number">1</span>;
    data[indexAT].P += <span class="hljs-number">3</span>;
    <span class="hljs-comment">// Home team register a loss</span>
    data[indexHT].L += <span class="hljs-number">1</span>;
  }
}
</code></pre>
<p>Now, we just need to add the data to the table, and we're done!</p>
<div class="hn-embed-widget" id="three-dots-separator"></div><p> </p>
<p>Note: I added some tailwind classes to make it look better, </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://codepen.io/marcelozarate/pen/YzxYOZj">https://codepen.io/marcelozarate/pen/YzxYOZj</a></div>
<p>Play around with the code snippet, modifying the matches, you will see instant changes in the table without further actions. Sweet!</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[13 fears every developer has experienced]]></title><description><![CDATA[Good day fellow reader, it's Halloween! 🎃 And what a better way to commemorate it than bringing up all those fears that haunt us all over the year. Are you ready? Beware, it is gonna get spooky!




Deploying 📤
Whenever it comes to deploying, the b...]]></description><link>https://marcelozarate.com/13-fears-every-developer-has-experienced</link><guid isPermaLink="true">https://marcelozarate.com/13-fears-every-developer-has-experienced</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[social]]></category><category><![CDATA[tips]]></category><category><![CDATA[Blogging]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Sun, 31 Oct 2021 13:20:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635641156817/HMYNS18QI.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day fellow reader, it's Halloween! 🎃 And what a better way to commemorate it than bringing up all those fears that haunt us all over the year. Are you ready? Beware, it is gonna get spooky!</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635686349535/2wZ0N9yMB.webp" alt="dancing-pumpkin.webp" />
</center>

<h1 id="deploying">Deploying 📤</h1>
<p>Whenever it comes to deploying, the bigger the project, the bigger the fear. Even if you are the author of every line of the code, tested it, reviewed it, there will be at some point fear of "what if x breaks", especially if people are dependant on your product.</p>
<h1 id="responsable-for-a-project">Responsable for a project 📊</h1>
<p>No matter if you work solo, in a startup, or a big team. Being responsible for a project gives great opportunities, but also raises some questions: What happens if this fails? If someone else screws this, I'm the one who will be taking the blame. Chills.</p>
<h1 id="bad-bosses">Bad bosses 🧛</h1>
<p>If you never had a bad boss, lucky you! Having a boss that doesn't know the area, or that is excessively self-centered, is an instant card for losing motivation, doing stuff that you don't like, and having to answer and lose time to what his highness thinks is the best.</p>
<h1 id="impostor-syndrome">Impostor syndrome 👽</h1>
<p>Well, this one has been over-debated here. Not being able to deliver, having lots of thoughts about your real capabilities, thinking you are a fraud and others deserve more than you. I'm pretty positive every one of you, in small or big amounts, have experienced this.</p>
<h1 id="hackathons">Hackathons 👩‍💻</h1>
<p>Hackathons are fun! For the organizers, maybe. This kind of event puts a lot of stress on you, and even if you won't get killed for losing, you probably will be sleeping little, eating too much, and counting minutes to finally deliver a poorly customized fork that wins the first prize.</p>
<h1 id="poor-management-of-time">Poor management of time 📅</h1>
<p>Kind of related to the above, but dealing with deadlines is the closest thing to having a zombie chasing you. Slow, but steady, it's gonna get you. Oooooh, it is.</p>
<h1 id="coding-challenges">Coding challenges 🧮</h1>
<p>I'm talking about the ones that recruiters and companies owners seem to like most. Inversion of binary trees, fizzbuzz stuff, working with date and time with no libraries, converting an array of dictionary arrays to another structure, you name it. This kind of challenge has nothing to do with the final work you are going (and are qualified) to do. Yet, you will be struggling with these algorithms and having the fear it keeps you out of your real ideal job. Unless you are applying for a coding challenges site developer. Never thought of that.</p>
<h1 id="writing-documentation">Writing documentation 📄</h1>
<p>This is really odd, because if you work on your own, probably you deal with this fear by postponing it. Be aware that by doing that you are only increasing the problem by having to deal with a big amount of documentation later on. Good luck with that.</p>
<h1 id="social-interactions">Social interactions 🤼</h1>
<p>Oh, well, from having to speak to an audience, to talking to a colleague to let him/her know they did something wrong, social interactions fears may vary, but they are of the same kind and affect relations equally. If you are in the dev industry, you probably got a "socially awkward" tattoo on your forehead. Let's gradually change that, please.</p>
<h1 id="fear-to-change">Fear to change 🎢</h1>
<p>Guilty! to be honest. It's in human nature, the need to stick to what comforts us, makes us feel in a safe place, reducing the uncertainty and the bad surprises. Stop! Sometimes you need to start from scratch, redo all previous month's work, or refactor everything into a library that better suits your needs. Overcome that instinct and it will be like a superhero power, I promise.</p>
<h1 id="being-forced-to-work-with-tech-you-dont-like">Being forced to work with tech you don't like 📠</h1>
<p>Related to the above, having to change, learn a new tech or framework, even another language, makes us feel insecure. Sometimes we are forced to work with something we are good at, but that we don't like. Admit it, you experienced those feelings at least once.</p>
<h1 id="getting-asked-to-fix-computers">Getting asked to fix computers 👨‍🔧</h1>
<p>If you have never been asked to fix a computer raise your hand. No one? Really? Well, I guess you all had nice moments when you get asked what do you do for a living. There is nothing less than horror in our faces when your mother's neighbor wants to bring you his 2GB Atom PC for fixing because is too slow. Or after everything stopped working after the latest Windows 10 update. I use arch btw.</p>
<h1 id="losing-an-entire-project">Losing an entire project 🗑️</h1>
<p>I will always remember when my web partner at the University accidentally <code>rm -rf</code> on the project a week before the deadline. That should be scarier than any Halloween costume, come on! I've seen posts offering impressive rewards to get back that stolen laptop/PC, just for the information inside. Luckily we all have to the cloud now, but there is always a chance you relax for your personal stuff.</p>
<div class="hn-embed-widget" id="three-dots-separator"></div><center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635685466020/nQTqkigCR.gif" alt="costume-halloween-friends.gif" />
</center>

<p>Hope I scared you enough! Happy Hallodev!</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[15 ways to remove elements from an array]]></title><description><![CDATA[Good day fellow reader, today I will show you fifteen different ways to remove elements from a javascript array. Feel free to suggest more if you please!
Introduction
Removing elements from an array might sound like a trivial task in many languages. ...]]></description><link>https://marcelozarate.com/15-ways-to-remove-elements-from-an-array</link><guid isPermaLink="true">https://marcelozarate.com/15-ways-to-remove-elements-from-an-array</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[array]]></category><category><![CDATA[arrays]]></category><category><![CDATA[array methods]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Fri, 29 Oct 2021 11:47:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635508010984/qXpn19-kU.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day fellow reader, today I will show you fifteen different ways to remove elements from a javascript array. Feel free to suggest more if you please!</p>
<h1 id="introduction">Introduction</h1>
<p>Removing elements from an array might sound like a trivial task in many languages. However, in Javascript, there are multiple ways to achieve this desired result, depending on <em>knowing the index</em> of the item, or just <em>knowing its value</em>. Some options are more performant than others, some are easier to read, be sure to check them all out and <strong>use what best suits your needs.</strong></p>
<p>You can remove an element or elements group of an array using: </p>
<ul>
<li><strong>length change:</strong> chop the end of the array.</li>
<li><strong>shift:</strong> removes an element from the start of the array.</li>
<li><strong>splice:</strong> removes elements from a specific array index.</li>
<li><strong>pop:</strong> removes an element from the end of the array.</li>
<li><strong>custom code:</strong> writing custom lines/functions to achieve the removal.</li>
<li><strong>libraries:</strong> using javascript libraries to remove items.</li>
<li><strong>filter:</strong> filter elements by value and return the desired ones.</li>
</ul>
<p><em>Note: Filter will be kind of an exception here because every option presented mutates the original array. And filter does not. Still, it is advisable to use it if you don't need the original reference to the array.</em></p>
<p><strong>Let's get there folks! We'll see 15 ways to remove items from an array!</strong></p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635507338176/AR0IpcVid.webp" alt="joe-biden-folks-do-you-have-any-idea-what-this-clown-is-doing.webp" />
</center>

<h1 id="index-of-methods">Index of methods</h1>
<ul>
<li><a class="post-section-overview" href="#removing-by-index">Removing by index</a><ul>
<li><a class="post-section-overview" href="#removing-from-the-end">Removing from the end</a><ul>
<li><a class="post-section-overview" href="#with-arrpop">1) With arr.pop()</a></li>
<li><a class="post-section-overview" href="#changing-length">2) Changing length</a></li>
<li><a class="post-section-overview" href="#with-splice">3) With splice</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#removing-from-the-beginning">Removing from the beginning</a><ul>
<li><a class="post-section-overview" href="#using-shift">4) Using shift</a></li>
<li><a class="post-section-overview" href="#using-splice">5) Using splice</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#removing-from-anywhere">Removing from anywhere</a><ul>
<li><a class="post-section-overview" href="#splicing">6) Splicing</a></li>
<li><a class="post-section-overview" href="#custom-diy-solution">7) Custom DIY solution</a></li>
<li><a class="post-section-overview" href="#using-delete">8) Using delete</a></li>
<li><a class="post-section-overview" href="#using-lodash">9) Using lodash</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="post-section-overview" href="#removing-by-value">Removing by value</a><ul>
<li><a class="post-section-overview" href="#with-findindex-and-splice">10) With findIndex and splice</a></li>
<li><a target="_blank" href="the-good-ol-working-way">11) The good ol' working way</a></li>
<li><a class="post-section-overview" href="#using-lodash-to-remove-by-predicate">12) Using lodash to remove by predicate</a></li>
<li><a class="post-section-overview" href="#using-lodash-to-remove-by-value">13) Using lodash to remove by value</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#other-removal-methods">Other removal methods</a><ul>
<li><a class="post-section-overview" href="#just-remove-everything">14) Just remove everything</a></li>
<li><a class="post-section-overview" href="#bonus-using-filter-to-create-new-array-with-removed-items">15) Bonus: using filter to create new array with removed items</a></li>
</ul>
</li>
</ul>
<blockquote>
<p>Remember, all the methods presented mutate the original array. If you are interested in keeping the removed elements, look for the options that set the "removed" variable</p>
</blockquote>
<h2 id="removing-by-index">Removing by index</h2>
<h3 id="removing-from-the-end">Removing from the end</h3>
<h4 id="with-arrpop">With arr.pop()</h4>
<p>This will just remove the last element. Simple, powerful, universal.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> removed = arr.pop();
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (8)</span>
<span class="hljs-comment">// [1,2,3,4,5,6,7,8]</span>
</code></pre>
<h4 id="changing-length">Changing length</h4>
<p>You can truncate an array setting its length. Be warned, if you set it to a greater value than the current one, last element will be a non-iterable empty slot.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
arr.length = <span class="hljs-number">3</span>;
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (3)</span>
<span class="hljs-comment">// [1,2,3]</span>
</code></pre>
<h4 id="with-splice">With splice</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> howmany = <span class="hljs-number">7</span>;
<span class="hljs-keyword">let</span> removed = [];
<span class="hljs-keyword">if</span> (howmany &lt;= arr.length) {
    removed = arr.splice(arr.length - howmany, howmany);
} <span class="hljs-keyword">else</span> {
    removed = arr.splice(<span class="hljs-number">0</span>, arr.length);
}
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (2)</span>
<span class="hljs-comment">// [1,2]</span>
</code></pre>
<h3 id="removing-from-the-beginning">Removing from the beginning</h3>
<h4 id="using-shift">Using shift</h4>
<p>Removing only one element</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> removed = arr.shift();
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (8)</span>
<span class="hljs-comment">// [2,3,4,5,6,7,8,9]</span>
</code></pre>
<h4 id="using-splice">Using splice</h4>
<p>Removing multiple elements</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> howmany = <span class="hljs-number">3</span>;
<span class="hljs-keyword">let</span> removed = arr.splice(<span class="hljs-number">0</span>, howmany);
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (6)</span>
<span class="hljs-comment">// [4,5,6,7,8,9]</span>
</code></pre>
<h3 id="removing-from-anywhere">Removing from anywhere</h3>
<h4 id="splicing">Splicing</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> <span class="hljs-keyword">from</span> = <span class="hljs-number">1</span>;
<span class="hljs-keyword">let</span> to = <span class="hljs-number">3</span>;
<span class="hljs-keyword">let</span> removed = arr.splice(<span class="hljs-keyword">from</span>, to);
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (6)</span>
<span class="hljs-comment">// [1,5,6,7,8,9]</span>
</code></pre>
<h4 id="custom-diy-solution">Custom DIY solution</h4>
<p>This ones assumes 'from' &lt;= 'to'</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> <span class="hljs-keyword">from</span> = <span class="hljs-number">2</span>;
<span class="hljs-keyword">let</span> to = <span class="hljs-number">5</span>;

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-keyword">from</span>; i &lt; arr.length - (to - <span class="hljs-keyword">from</span>); i++) {
    arr[i] = arr[i + (to - <span class="hljs-keyword">from</span>)];
}
arr.length = arr.length - (to - <span class="hljs-keyword">from</span>);

<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (6)</span>
<span class="hljs-comment">// [1,2,6,7,8,9]</span>
</code></pre>
<h4 id="using-delete">Using delete</h4>
<p><em>Note: This one will leave undefined or empty spaces in the corresponding positions, the array size will not be changed.</em></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">delete</span> arr[<span class="hljs-number">0</span>];
<span class="hljs-keyword">delete</span> arr[<span class="hljs-number">4</span>];
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (9)</span>
<span class="hljs-comment">// [,2,3,4,,6,7,8,9]</span>
</code></pre>
<h4 id="using-lodash">Using lodash</h4>
<p>You need to install <a target="_blank" href="https://lodash.com/">lodash</a> in order to use this</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> removed = _.pullAt(arr, [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">8</span>]);
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (6)</span>
<span class="hljs-comment">// [3,4,5,6,7,8]</span>
</code></pre>
<h2 id="removing-by-value">Removing by value</h2>
<h4 id="with-findindex-and-splice">With findIndex and splice</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> people = [{
    <span class="hljs-attr">id</span>: <span class="hljs-number">15</span>,
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'John'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Doe'</span>
}, {
    <span class="hljs-attr">id</span>: <span class="hljs-number">16</span>,
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'Jane'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Doe'</span>
}, {
    <span class="hljs-attr">id</span>: <span class="hljs-number">20</span>,
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'Guy'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Incognito'</span>
}];

<span class="hljs-keyword">let</span> indexToRemove = people.findIndex(<span class="hljs-function"><span class="hljs-params">elem</span> =&gt;</span> elem.first_name === <span class="hljs-string">'John'</span>);
<span class="hljs-keyword">if</span> (indexToRemove !== <span class="hljs-number">-1</span>) {
    people.splice(indexToRemove, <span class="hljs-number">1</span>);
}
<span class="hljs-built_in">console</span>.log(people);
<span class="hljs-comment">// [object Array] (2)</span>
<span class="hljs-comment">// [{</span>
<span class="hljs-comment">//    id: 16,</span>
<span class="hljs-comment">//    first_name: 'Jane',</span>
<span class="hljs-comment">//    last_name: 'Doe'</span>
<span class="hljs-comment">// }, {</span>
<span class="hljs-comment">//    id: 20,</span>
<span class="hljs-comment">//    first_name: 'Guy',</span>
<span class="hljs-comment">//    last_name: 'Incognito'</span>
<span class="hljs-comment">// }]</span>
</code></pre>
<h4 id="the-good-ol-working-way">The good ol' working way</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> people = [{
    <span class="hljs-attr">id</span>: <span class="hljs-number">15</span>,
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'John'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Doe'</span>
}, {
    <span class="hljs-attr">id</span>: <span class="hljs-number">16</span>,
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'Jane'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Doe'</span>
}, {
    <span class="hljs-attr">id</span>: <span class="hljs-number">20</span>,
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'Guy'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Incognito'</span>
}];

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = people.length - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; i--) {
    <span class="hljs-keyword">if</span> (people[i].last_name === <span class="hljs-string">'Doe'</span>) {
        people.splice(i, <span class="hljs-number">1</span>);
    }
}
<span class="hljs-built_in">console</span>.log(people);
<span class="hljs-comment">// [object Array] (1)</span>
<span class="hljs-comment">// [{</span>
<span class="hljs-comment">//    id: 20,</span>
<span class="hljs-comment">//    first_name: 'Guy',</span>
<span class="hljs-comment">//    last_name: 'Incognito'</span>
<span class="hljs-comment">// }]</span>
</code></pre>
<h4 id="using-lodash-to-remove-by-predicate">Using lodash to remove by predicate</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> removed = _.remove(arr, <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item &gt; <span class="hljs-number">3</span>);
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (3)</span>
<span class="hljs-comment">// [1,2,3]</span>
</code></pre>
<h4 id="using-lodash-to-remove-by-value">Using lodash to remove by value</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
<span class="hljs-keyword">let</span> removed = _.pull(arr, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>);
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (6)</span>
<span class="hljs-comment">// [1,2,3,4,5,9]</span>
</code></pre>
<h2 id="other-removal-methods">Other removal methods</h2>
<h4 id="just-remove-everything">Just remove everything</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>];
arr.length = <span class="hljs-number">0</span>;
<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [object Array] (0)</span>
<span class="hljs-comment">// []</span>
</code></pre>
<h4 id="bonus-using-filter-to-create-new-array-with-removed-items">Bonus: using filter to create new array with removed items</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> words = [<span class="hljs-string">'spray'</span>, <span class="hljs-string">'limit'</span>, <span class="hljs-string">'elite'</span>, <span class="hljs-string">'exuberant'</span>, <span class="hljs-string">'destruction'</span>, <span class="hljs-string">'present'</span>];
<span class="hljs-keyword">const</span> newArr = words.filter(<span class="hljs-function"><span class="hljs-params">word</span> =&gt;</span> word != <span class="hljs-string">'elite'</span>);
<span class="hljs-built_in">console</span>.log(newArr);
<span class="hljs-comment">// [object Array] (5)</span>
<span class="hljs-comment">// ["spray", "limit", "exuberant", "destruction", "present"]</span>
</code></pre>
<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="final-thoughts">Final thoughts</h1>
<p>Phew! This article took more time than I estimated. Remember to use whatever fits your needs. Hope you find it useful!</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[Laravel 8 REST API with Sanctum]]></title><description><![CDATA[Good day, fellow reader.
Today I want to show you how easily you can build an authenticated API using the power of Laravel and Sanctum. 
So, buckle up, aaand it's lights out and away we go!


Max Verstappen - Formula 1 driver


Laravel8 REST API
For ...]]></description><link>https://marcelozarate.com/laravel-8-rest-api-with-sanctum</link><guid isPermaLink="true">https://marcelozarate.com/laravel-8-rest-api-with-sanctum</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Laravel]]></category><category><![CDATA[REST API]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Sun, 24 Oct 2021 23:01:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635116406623/cBqCj-_yC.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader.</p>
<p>Today I want to show you how easily you can build an authenticated API using the power of Laravel and Sanctum. </p>
<p>So, buckle up, aaand it's lights out and away we go!</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635019105789/Jt0GvEwwt.webp" alt="max-verstappen.webp" />
Max Verstappen - Formula 1 driver
</center>

<h1 id="laravel8-rest-api">Laravel8 REST API</h1>
<p>For this tutorial, you'll only need:</p>
<ul>
<li>Basic knowledge of Laravel framework.</li>
<li>Simple usage of a REST API Client (i.e.: <a target="_blank" href="https://insomnia.rest/">Insomnia </a>,  <a target="_blank" href="https://www.postman.com/">Postman </a>,  <a target="_blank" href="https://hoppscotch.io/">Hoppscotch</a>)</li>
<li>Vague idea of what a REST API is.</li>
</ul>
<blockquote>
<p>Don't you know exactly what a REST API is?  <a target="_blank" href="https://lo-victoria.com/a-deep-look-into-restful-apis">A deep look into RESTful APIs </a> by <a class="user-mention" href="https://hashnode.com/@victoria">Victoria Lo</a> got you covered in few lines</p>
</blockquote>
<h1 id="what-is-sanctum">What is Sanctum?</h1>
<p>As per the official  <a target="_blank" href="https://laravel.com/docs/8.x/sanctum">documentation</a> </p>
<blockquote>
<p>Laravel Sanctum provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs. Sanctum allows each user of your application to generate multiple API tokens for their account. These tokens may be granted abilities / scopes which specify which actions the tokens are allowed to perform.</p>
</blockquote>
<h1 id="preparing-the-laravel-project">Preparing the Laravel project</h1>
<p>We'll start with a fresh Laravel 8 API project.</p>
<pre><code class="lang-bash">composer create-project --prefer-dist laravel/laravel sanctum-api
</code></pre>
<p>The good news is, Sanctum is already installed and configured for you in Laravel 8! </p>
<p>You'll only need to setup your local database in <code>.env</code> file and you're good to go</p>
<pre><code><span class="hljs-attr">DB_CONNECTION</span>=mysql
<span class="hljs-attr">DB_HOST</span>=<span class="hljs-number">127.0</span>.<span class="hljs-number">0.1</span>
<span class="hljs-attr">DB_PORT</span>=<span class="hljs-number">3306</span>
<span class="hljs-attr">DB_DATABASE</span>=sanctum-api
<span class="hljs-attr">DB_USERNAME</span>=root
<span class="hljs-attr">DB_PASSWORD</span>=mysecretpassword
</code></pre><p>Now, we need to migrate our database data. As you probably know, doing that in Laravel is easy as:</p>
<pre><code class="lang-bash">php artisan migrate
</code></pre>
<h1 id="writing-the-controllers">Writing the controllers</h1>
<p>We are going to use the <code>User</code> model, that comes with default Laravel. You don't need to add the <code>HasApiTokens</code> trait to the model, nor configure anything in <code>RouteServiceProvider.php</code>. This version of Laravel already addressed it for you.</p>
<p>Now, let's create the controller for handling the auth requests.</p>
<pre><code class="lang-console">php artisan make:controller AuthController
</code></pre>
<h3 id="registering-via-api">Registering via API</h3>
<p>In there we will add the register function to handle registration within the Laravel 8 API</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">register</span>(<span class="hljs-params">Request $request</span>) </span>{
    $validated = $request-&gt;validate([
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'required|string|max:255'</span>,
        <span class="hljs-string">'email'</span> =&gt; <span class="hljs-string">'required|string|email|max:255|unique:users'</span>,
        <span class="hljs-string">'password'</span> =&gt; <span class="hljs-string">'required|string|min:8'</span>,
    ]);

    $user = User::create([
        <span class="hljs-string">'name'</span> =&gt; $validated[<span class="hljs-string">'name'</span>],
        <span class="hljs-string">'email'</span> =&gt; $validated[<span class="hljs-string">'email'</span>],
        <span class="hljs-string">'password'</span> =&gt; Hash::make($validated[<span class="hljs-string">'password'</span>]),
    ]);

    $token = $user-&gt;createToken(<span class="hljs-string">'auth_token'</span>)-&gt;plainTextToken;

    <span class="hljs-keyword">return</span> response()-&gt;json([
        <span class="hljs-string">'access_token'</span> =&gt; $token,
        <span class="hljs-string">'token_type'</span> =&gt; <span class="hljs-string">'Bearer'</span>,
    ]);
}
</code></pre>
<p>What's going on here? Well, the first two parts are Laravel's basic way to validate a request and create a User with the validated data.</p>
<p>The juicy stuff Sanctum-wise is here:</p>
<p><code>$token = $user-&gt;createToken('auth_token')-&gt;plainTextToken;</code></p>
<p>We need the <code>plainTextToken</code> to pass it to the client. This is done by Sanctum. The token would be a string like <code>6|BNh21lDInxW8Zj00ZMUM7ZaZ9kPxV45yhIA76Tfk</code>. We return the JSON response with the token_type as Bearer, we can use it to hit the protected Laravel 8 API endpoints right away.</p>
<h3 id="log-in-via-laravel-8-api">Log in via Laravel 8 API</h3>
<p>But, what happens if we forget our token? We should log in to retrieve one, so we need to write a controller function for it.</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">login</span>(<span class="hljs-params">Request $request</span>) </span>{
    <span class="hljs-keyword">if</span> (!Auth::attempt($request-&gt;only(<span class="hljs-string">'email'</span>, <span class="hljs-string">'password'</span>))) {
         <span class="hljs-keyword">return</span> response()-&gt;json([<span class="hljs-string">'message'</span> =&gt; <span class="hljs-string">'Incorrect e-mail or password'</span>], <span class="hljs-number">401</span>);
    }

    $user = User::where(<span class="hljs-string">'email'</span>, $request[<span class="hljs-string">'email'</span>])-&gt;firstOrFail();

    $token = $user-&gt;createToken(<span class="hljs-string">'auth_token'</span>)-&gt;plainTextToken;

    <span class="hljs-keyword">return</span> response()-&gt;json([
        <span class="hljs-string">'access_token'</span> =&gt; $token,
        <span class="hljs-string">'token_type'</span> =&gt; <span class="hljs-string">'Bearer'</span>,
    ]);
}
</code></pre>
<p>As you can see, the last part is identical to the previous, only this time we try to log in the user with the request data, instead of creating a new one.</p>
<h3 id="protected-route-handling-in-api">Protected route handling in API</h3>
<p>Finally, we will add a simple controller handle for the endpoint that would return the current user. These will be authenticated users only. You can add that restriction in the controller, but I believe it's cleaner to do it in the routes file.</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">whoami</span>(<span class="hljs-params">Request $request</span>) </span>{
    <span class="hljs-keyword">return</span> $request-&gt;user();
}
</code></pre>
<h1 id="routes-for-the-rest-api">Routes for the REST API</h1>
<p>The routes for an API shouldn't be in the usual <code>routes\web.php</code>. We will use the auto-generated <code>routes\api.php</code> one.</p>
<p>This brings at least two benefits:</p>
<ul>
<li>Separated routes from our app to the ones that are API-based.</li>
<li>Auto-prefixing: The API prefix is automatically inserted in every route we code there.</li>
</ul>
<pre><code class="lang-php">Route::post(<span class="hljs-string">'/register'</span>, [AuthController::class, <span class="hljs-string">'register'</span>]);
Route::post(<span class="hljs-string">'/login'</span>, [AuthController::class, <span class="hljs-string">'login'</span>]);
Route::middleware(<span class="hljs-string">'auth:sanctum'</span>)-&gt;get(<span class="hljs-string">'/whoami'</span>, [AuthController::class, <span class="hljs-string">'whoami'</span>]);
</code></pre>
<p><em>See that middleware in the third route? That means that route will only be accessible by authorized users.</em></p>
<h1 id="using-the-laravel-8-rest-api">Using the Laravel 8 REST API</h1>
<p>We are going to test our application using the <code>php artisan serve</code> command, which starts a Laravel development server for default at <code>http://127.0.0.1:8000</code></p>
<p>You can use any REST client, I'm using  <a target="_blank" href="https://insomnia.rest/download">Insomnia</a>  for this guide.</p>
<h3 id="setting-up-the-headers">Setting up the headers</h3>
<p>Add "Accept: application/json" to the headers so you avoid html responses from Laravel.</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635097533167/WYCC-WD-7.png" alt="1-headers.png" />
</center>

<h3 id="register-post-json">Register (Post / JSON)</h3>
<h4 id="using-data-that-will-not-validate">Using data that will not validate</h4>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635097461975/b_c72ikX3.png" alt="2-registerinvalid.png" />
</center>

<h4 id="registering-with-valid-data">Registering with valid data</h4>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635097639635/Vs1TUsPPN.png" alt="2-registervalid.png" />
</center>

<h4 id="logging-in-with-invalid-data">Logging in with invalid data</h4>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635097696086/0HaFfZWrH.png" alt="4-logininvalid.png" />
</center>

<h4 id="logging-in-with-valid-data">Logging in with valid data</h4>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635097754833/-pmuzSRmv.png" alt="5-loginvalid.png" />
</center>

<h4 id="who-am-i-not-being-authenticated">Who am I? Not being authenticated</h4>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635098498760/njbXxBFJB.png" alt="6-whoami-notauth.png" />
</center>

<h4 id="who-am-i-authenticated">Who am I? Authenticated</h4>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635098541184/dWPgK1RP5.png" alt="7-usebearertoken.png" />
</center>

<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="full-code-of-laravel-8-api-additions-to-default-laravel-8-code">Full code of Laravel 8 API (additions to default Laravel 8 code)</h1>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="7fddedbe938d7b089569391648fc7ec8"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/marcelozarate/7fddedbe938d7b089569391648fc7ec8" class="embed-card">https://gist.github.com/marcelozarate/7fddedbe938d7b089569391648fc7ec8</a></div><h1 id="summary">Summary</h1>
<p>This was a simple example, yet, you can extend it for your models, and you'll already have a working token-based authentication in your project. Hope you enjoyed it!</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[First Pull Request]]></title><description><![CDATA[Good day, fellow reader.
It's  hacktoberfest  time! And I want to share with you my first contribution to Open Source. If you are new to this, or never contributed to Open Source Software, I hope this can be inspiring. I will try to make it as short ...]]></description><link>https://marcelozarate.com/first-pull-request</link><guid isPermaLink="true">https://marcelozarate.com/first-pull-request</guid><category><![CDATA[Open Source]]></category><category><![CDATA[#hacktoberfest ]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[newbie]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Wed, 20 Oct 2021 14:28:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634685277882/YwasFmu0-.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader.</p>
<p>It's  <a target="_blank" href="https://hacktoberfest.digitalocean.com/">hacktoberfest</a>  time! And I want to share with you my first contribution to Open Source. If you are new to this, or never contributed to Open Source Software, <strong>I hope this can be inspiring</strong>. I will try to make it as short as it was actually doing it.</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634686013028/1C92TnlMu.webp" alt="im-ready-cat.webp" />
</center>

<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="my-first-pr">My first PR</h1>
<p>Back in 2016, I was working on a project that implemented a dual list box, using a library called Bootstrap Dual Listbox.</p>
<blockquote>
<p>Bootstrap Dual Listbox is a responsive dual listbox widget optimized for Twitter Bootstrap.</p>
</blockquote>
<p>And it looks like this</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634686113204/_e_ZuW9xX.png" alt="duallistbox-bootstrap-example" />
</center>

<p>The thing is, I needed to make custom stuff if an item was moved, but, the default behavior was moving the item. </p>
<p>If I edited the code of the script, that should work. But, if an update to the plugin came around in the future, I wasn't going to be able to auto-update, otherwise <strong>I would lose my custom changes.</strong></p>
<p>So I did some research and decided to try to open a Pull Request and put my changes there.</p>
<blockquote>
<p>I wish I had this <a target="_blank" href="https://iambami.dev/step-by-step-guide-to-get-started-with-open-source-as-a-beginner-ckuitlxlp0khh8ws19w0o03a9">tutorial</a> by <a class="user-mention" href="https://hashnode.com/@Iambami"> atinuke oluwabamikemi kayode</a> when I started </p>
</blockquote>
<h1 id="the-actual-code">The actual code</h1>
<p><em>Note: Feel free to move to the next part if you are not interested in the code, but in the experience of contributing to OSS.</em></p>
<p>I added 4 new options to the plugin defaults</p>
<pre><code class="lang-javascript">defaults = {
  <span class="hljs-comment">// Ommited code</span>
  <span class="hljs-attr">eventMoveOverride</span>: <span class="hljs-literal">false</span>,                                                           <span class="hljs-comment">// boolean, allows user to unbind default event behaviour and run their own instead</span>
  <span class="hljs-attr">eventMoveAllOverride</span>: <span class="hljs-literal">false</span>,                                                        <span class="hljs-comment">// boolean, allows user to unbind default event behaviour and run their own instead</span>
  <span class="hljs-attr">eventRemoveOverride</span>: <span class="hljs-literal">false</span>,                                                         <span class="hljs-comment">// boolean, allows user to unbind default event behaviour and run their own instead</span>
  <span class="hljs-attr">eventRemoveAllOverride</span>: <span class="hljs-literal">false</span>                                                       <span class="hljs-comment">// boolean, allows user to unbind default event behaviour and run their own instead</span>
}
</code></pre>
<p>Then change this</p>
<pre><code class="lang-javascript">dualListbox.elements.moveButton.on(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  move(dualListbox);
});
</code></pre>
<p>To this</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (dualListbox.settings.eventMoveOverride === <span class="hljs-literal">false</span>) {
  dualListbox.elements.moveButton.on(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    move(dualListbox);
  });
}
</code></pre>
<p>for every one of the 4 options.</p>
<p>After that, I wrote the calls to apply settings</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">this</span>.setEventMoveOverride(<span class="hljs-built_in">this</span>.settings.eventMoveOverride);
<span class="hljs-built_in">this</span>.setEventMoveAllOverride(<span class="hljs-built_in">this</span>.settings.eventMoveAllOverride);
<span class="hljs-built_in">this</span>.setEventRemoveOverride(<span class="hljs-built_in">this</span>.settings.eventRemoveOverride);
<span class="hljs-built_in">this</span>.setEventRemoveAllOverride(<span class="hljs-built_in">this</span>.settings.eventRemoveAllOverride);
</code></pre>
<p>And of course the options setter for every one of the four setters</p>
<pre><code class="lang-javascript">setEventMoveOverride: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, refresh</span>) </span>{
  <span class="hljs-built_in">this</span>.settings.eventMoveOverride = value;
  <span class="hljs-keyword">if</span> (refresh) {
    refreshSelects(<span class="hljs-built_in">this</span>);
  }
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.element;
},
</code></pre>
<p>And that's it! Well, actually no. <strong>Don't forget to extend the documentation</strong> if needed</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>eventMoveOverride<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span>: set this to <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> to allow your own implementation of the move event.<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>setEventMoveOverride(value, refresh)<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>change the <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>eventMoveOverride<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> parameter.<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
</code></pre>
<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="pr-was-not-merged">PR was not merged</h1>
<p>Looking at the Pull Requests Github page, I saw that there were a lot of PRs waiting for review or merging. So I assumed the repo owner would be inactive or busy, so, I googled and find the author's email and sent him this email</p>
<blockquote>
<p>Hi Istvan!</p>
<p>First of all, thanks for this great plugin! I'm using it for the first time and it is just delightful.
However, it could be more customizable, and I hope GitHub community will look forward to contributing to your work.</p>
<p>Reading through the Github page I acknowledged you don't have too much time, but, can you please take a look at the open pull requests?
If you can, check out this:
https://github.com/istvan-ujjmeszaros/bootstrap-duallistbox/pull/89</p>
<p>That would be awesome!</p>
<p>Cheers, Marcelo.</p>
</blockquote>
<p>I received a response within half an hour, and <strong>the PR was merged.</strong> </p>
<p><em>However, I learned afterward that this kind of stalking is not a good practice and you should really consider if you are annoying someone. (I still believe I didn't in this particular case, do you think I did?)
</em></p>
<h1 id="it-is-merged">It is merged</h1>
<p>That was awesome! Now not only do I have the extra functionality available but, <strong>with the same amount of work, other people could benefit from it.</strong></p>
<blockquote>
<p>Want to start contributing yourself?  <a target="_blank" href="https://blog.avneesh.tech/finding-the-right-open-source-projects-to-contribute-to">This guide</a> by <a class="user-mention" href="https://hashnode.com/@avneesh0612">Avneesh Agarwal</a> gives you a great starting point.</p>
</blockquote>
<p><strong>Happy hacktoberfest!</strong></p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[Why I almost don't choose Hashnode]]></title><description><![CDATA[Good day, fellow reader.
Before I ever started considering writing, I did some research to find out which platform would be a better fit for me. I looked into several of them. And finally opted for Hashnode, because it provides a few key features.
Th...]]></description><link>https://marcelozarate.com/why-i-almost-dont-choose-hashnode</link><guid isPermaLink="true">https://marcelozarate.com/why-i-almost-dont-choose-hashnode</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[tips]]></category><category><![CDATA[HashnodeCommunity]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Sat, 16 Oct 2021 13:20:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634298686066/lY9sK8Egl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader.</p>
<p>Before I ever started considering writing, I did some research to find out which platform would be a better fit for me. I looked into several of them. And finally opted for Hashnode, because it provides a few key features.</p>
<h1 id="three-pros-most-important-ones">Three pros (most important ones)</h1>
<ol>
<li><p><strong>CONTENT OWNERSHIP</strong>. Caps are not accidental. This includes the option to set up custom domains for your <a target="_blank" href="https://marcelozarate.com">blog</a> </p>
</li>
<li><p>A community that is not only welcoming to newbies but also dynamic and diverse.</p>
</li>
<li><p>No paywall (I'm an advocate of freedom of information)</p>
</li>
</ol>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634250917656/lS0v2HHAa.gif" alt="Barney Stinson ironic thumbs up" />
<em>Barney Stinson from How I met your mother (TV Series)</em>
</center>

<h1 id="three-cons">Three cons</h1>
<p>Well, it's not a land of roses around here, there was something I really liked from other platforms I couldn't find in Hashnode. It was a boomer. Those three little things were the difference between a normal article, and a <em>LEGEN-DARY</em> one.
And those three things were this</p>
<div class="hn-embed-widget" id="three-dots-separator"></div><p>What? Yeah, those three little dots, the horizontal rule from other platforms, so simple, yet so elegant. I wanted them. And I wanted them badly. I couldn't find an already made solution for this. So I borrowed some of the code from other fronts, and decided to do my own widget. That way I could easily insert that three dots everywhere in my articles.</p>
<blockquote>
<p>Don't you know how to create a widget for hashnode? <a class="user-mention" href="https://hashnode.com/@Catalinpit">Catalin Pit</a> explains it <a target="_blank" href="https://townhall.hashnode.com/hashnode-widgets">step by step</a></p>
</blockquote>
<h1 id="three-dots-separator-horizontal-ellipsis">Three dots separator (horizontal ellipsis)</h1>
<p>To create it, I set widgetid as <code>three-dots-separator</code> so I could use like this in my articles</p>
<pre><code class="lang-markdown">%%[three-dots-separator]
</code></pre>
<p>and the markup as follows   </p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span><span class="css">
<span class="hljs-selector-class">.three-dots-separator</span> {
 <span class="hljs-attribute">box-sizing</span>: border-box;
 <span class="hljs-attribute">display</span>: flex;
 <span class="hljs-attribute">justify-content</span>: center;
 <span class="hljs-attribute">text-decoration</span>: none solid <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.8</span>);
 <span class="hljs-attribute">margin</span>: <span class="hljs-number">32px</span> <span class="hljs-number">0px</span> <span class="hljs-number">14px</span>;
 <span class="hljs-attribute">padding</span>: <span class="hljs-number">24px</span> <span class="hljs-number">0px</span> <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.first-dot</span>, <span class="hljs-selector-class">.second-dot</span> {
 <span class="hljs-attribute">box-sizing</span>: border-box;
 <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.8</span>);
 <span class="hljs-attribute">display</span>: block;
 <span class="hljs-attribute">height</span>: <span class="hljs-number">3px</span>;
 <span class="hljs-attribute">width</span>: <span class="hljs-number">3px</span>;
 <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">8</span>, <span class="hljs-number">8</span>, <span class="hljs-number">8</span>) none repeat scroll <span class="hljs-number">0%</span> <span class="hljs-number">0%</span> / auto padding-box border-box;
 <span class="hljs-attribute">margin</span>: <span class="hljs-number">0px</span> <span class="hljs-number">20px</span> <span class="hljs-number">0px</span> <span class="hljs-number">0px</span>;
 <span class="hljs-attribute">outline</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.8</span>) none <span class="hljs-number">0px</span>;
}

<span class="hljs-selector-class">.third-dot</span> {
 <span class="hljs-attribute">box-sizing</span>: border-box;
 <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.8</span>);
 <span class="hljs-attribute">display</span>: block;
 <span class="hljs-attribute">height</span>: <span class="hljs-number">3px</span>;
 <span class="hljs-attribute">width</span>: <span class="hljs-number">3px</span>;
 <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">8</span>, <span class="hljs-number">8</span>, <span class="hljs-number">8</span>) none repeat scroll <span class="hljs-number">0%</span> <span class="hljs-number">0%</span> / auto padding-box border-box;
 <span class="hljs-attribute">outline</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.8</span>) none <span class="hljs-number">0px</span>;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"three-dots-separator"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"separator"</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"first-dot"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"second-dot"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"third-dot"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634323123801/qAMJIVP3y.webp" alt="Barney Stinson Genuine Thumbs up" />
</center>

<p>Hope you like it, feel free to use it, improve it, and comment with any suggestions you have!</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[Javascript false expressions evaluating to true]]></title><description><![CDATA[Good day, fellow reader.
As a programmer, I sometimes need to jump between languages, and changing not only involves a different syntax but also setting up your mind to the tricky or handy ways things are done in every one of them.


Doc from "Back t...]]></description><link>https://marcelozarate.com/javascript-false-expressions-evaluating-to-true</link><guid isPermaLink="true">https://marcelozarate.com/javascript-false-expressions-evaluating-to-true</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[#codenewbies]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[ecmascript]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Fri, 15 Oct 2021 14:48:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634298604553/_-xnwoxRX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader.</p>
<p>As a programmer, I sometimes need to jump between languages, and changing not only involves a different syntax but also setting up your mind to the tricky or handy ways things are done in every one of them.</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634249371567/jbC8GiwqP.webp" alt="Ready doc from back to the future" />
<em>Doc from "Back to the future" (Movie)</em>
</center>

<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="the-bug">The bug 🐞</h1>
<p>I switched to Javascript, and I was debugging something (a Node.js API). It seemed that some part of a really long task was not working properly. Then, just before going into debug mode, I saw it. I mean, for a JS-only developer this might be an easy spot.</p>
<p>The simplified version of the code was:</p>
<pre><code class="lang-javascript">res = <span class="hljs-keyword">await</span> fetchDataFromDatabase(transaction);
<span class="hljs-keyword">if</span> (res) {
  responseObject.response = res;
 <span class="hljs-comment">// more stuff</span>
}
<span class="hljs-comment">// Continue from here if res is empty?</span>
</code></pre>
<p>So, when <code>res</code>  was <code>[]</code> <em>(semantically an empty response)</em>, the if was evaluated to <code>true</code>, and the "more stuff" part was done. <strong>That is pretty different from other languages</strong>, and I will just demonstrate a few.</p>
<h3 id="php">PHP</h3>
<pre><code class="lang-php"><span class="hljs-keyword">if</span> ([]) {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"won't get here"</span>;
} <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"empty arrays evaluate to false"</span>;
}
<span class="hljs-comment">// Output: empty arrays evaluate to false</span>
</code></pre>
<h3 id="python">Python</h3>
<pre><code class="lang-python">res = []
<span class="hljs-keyword">if</span> res:
    <span class="hljs-keyword">print</span> (<span class="hljs-string">"never got here"</span>)
<span class="hljs-keyword">else</span>:
    <span class="hljs-keyword">print</span> (<span class="hljs-string">"empty arrays evaluate to false"</span>)
<span class="hljs-comment"># Output: empty arrays evaluate to false</span>
</code></pre>
<h3 id="java">Java</h3>
<p>The thing gets interesting here:</p>
<pre><code class="lang-java">String[] res;
<span class="hljs-keyword">if</span>(res) {
    System.out.println(<span class="hljs-string">"ENTERED"</span>);
}
</code></pre>
<p>Will throw a nice <code>incompatible types: String[] cannot be converted to boolean</code></p>
<h3 id="c-c">C / C++</h3>
<p>Oh, that won't even be a problem because why would you want an empty array in C.</p>
<h1 id="the-reason">The reason 🤙</h1>
<p>Of course, there was an explanation for that behavior. But let me say that if you go to the console and do:</p>
<pre><code class="lang-javascript">[] == <span class="hljs-literal">false</span>
<span class="hljs-comment">// output is true</span>
</code></pre>
<p>But if you continue in the console and try this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> ([]) {
    <span class="hljs-string">"yes"</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-string">"no"</span>
}
<span class="hljs-comment">// output is yes</span>
</code></pre>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634242323263/OPKGsmeRK.gif" alt="What the hell is going on here - Biff - Back to the future 2" />
<em>Biff from "Back to the future part II" (Movie)</em>
</center>

<p>I know Biff, wasn't <code>[]</code> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion">type coerced</a> to false? </p>
<p>Under the hood, things happen. Consider these statements.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (Expression) {}
<span class="hljs-keyword">while</span> (Expression) {}
</code></pre>
<p>According to ECMAScript 2021 Language Specification, after an expression is evaluated, a <a target="_blank" href="https://262.ecma-international.org/12.0/#sec-toboolean">ToBoolean</a> function is called for that value. 
That function <code>ToBoolean(argument)</code> will return <code>argument</code> if it is of type Boolean (<code>true</code> or <code>false</code>) otherwise, it is going to cast it according to the following table:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>argument</td><td>ToBoolean(argument)</td></tr>
</thead>
<tbody>
<tr>
<td>false</td><td>false</td></tr>
<tr>
<td>0</td><td>false</td></tr>
<tr>
<td>-0</td><td>false</td></tr>
<tr>
<td>0n</td><td>false</td></tr>
<tr>
<td>"", '', ``</td><td>false</td></tr>
<tr>
<td>null</td><td>false</td></tr>
<tr>
<td>undefined</td><td>false</td></tr>
<tr>
<td>NaN</td><td>false</td></tr>
<tr>
<td>document.all</td><td>false</td></tr>
<tr>
<td><strong>everything else</strong></td><td><strong>true</strong></td></tr>
</tbody>
</table>
</div><blockquote>
<p>The first 9 rows are known as <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy">Falsy</a> values.</p>
<p>Everything else is returned as <code>true</code> in the ToBoolean function. Those values are known as <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy">Truthy</a> values</p>
</blockquote>
<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="whats-important-here">What's important here ❗</h1>
<p>So, remembering the falsies, we can be certain that every other value/object will be evaluated as <code>true</code>. <strong>And that includes our beloved []</strong></p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div>]]></content:encoded></item><item><title><![CDATA[Create your database using Python and SQLite]]></title><description><![CDATA[Good day, fellow reader.
There are a lot of options when it comes to saving the data you or your app generates:

Store it on memory: it will be lost when you close the app or reboot your machine.

Save it to a file: Easy to write, not that easy to re...]]></description><link>https://marcelozarate.com/create-your-database-using-python-and-sqlite</link><guid isPermaLink="true">https://marcelozarate.com/create-your-database-using-python-and-sqlite</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[SQLite]]></category><category><![CDATA[Python]]></category><category><![CDATA[python beginner]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Sun, 10 Oct 2021 23:21:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633907472285/x_jNeJmyd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader.</p>
<p>There are a lot of options when it comes to saving the data you or your app generates:</p>
<ul>
<li><p><strong>Store it on memory:</strong> it will be lost when you close the app or reboot your machine.</p>
</li>
<li><p><strong>Save it to a file:</strong> Easy to write, not that easy to read from it, and keeping consistency might be challenging.</p>
</li>
<li><p><strong>Store it in a database:</strong> you guessed it, the way-to-go in this tutorial.</p>
</li>
<li><p><strong>Save it to the cloud:</strong> a wise choice, if you know a blogger who has done a tutorial on this, please write a comment.</p>
</li>
</ul>
<p>We are going to create our own database, schema, and insert and modify data over it!</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633731729444/swI1_nScY.webp" alt="sheldon.webp" />
<em>Sheldon Cooper from The Big Bang Theory (TV Series)</em>
</center>

<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="introduction">Introduction</h1>
<p>I'm a person who is not a big fan of the <em>"foo, bar, baz"</em> examples. I believe that real knowledge strikes in when you apply a concept to a real situation. So we're going that way. It's a simplified version of a real problem I solved a few months ago. This version uses no classes, so, if you are new to this, you can follow along with no problems. </p>
<p>We are going to use  <a target="_blank" href="https://www.sqlite.org/">SQLite</a>, a popular relational database management system that does not require a lot of configuration to start using, it is rather embedded into the final program. To perform actions over that set of data, we are going to use  <a target="_blank" href="https://www.python.org/">python</a>.</p>
<p>Are you absolutely new to the SQL world? You can start reading  <a target="_blank" href="https://shreyaskulkarni.hashnode.dev/essential-sql-for-beginners">"Essential SQL for beginners"</a>  by <a class="user-mention" href="https://hashnode.com/@shreyaskulkarni">Shreyas Kulkarni</a>.
If you also never coded a line a Python, the series in <a class="user-mention" href="https://hashnode.com/@codinglayla">Layla</a>'s blog that starts with  <a target="_blank" href="https://laylacodes.hashnode.dev/python-basics-keywords-identifiers-and-indention">Python basics</a> it's going to help you out. I'll wait here.</p>
<h1 id="the-problem">The problem</h1>
<p>We are going to work with a small business that mainly needs to store its suppliers and the products they deliver.</p>
<ul>
<li>They need to store the supplier's name, its address is optional.</li>
<li>They must store the product descriptions, and the quantity.</li>
<li>Every product they have is only bought from one supplier.</li>
</ul>
<h1 id="the-design">The design</h1>
<p>We can make a diagram of our database and it will look like this</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633731238261/vy1aYWB5V.png" alt="dbdiagram.PNG" />
<em>Our database diagram and the relation between tables</em>
</center>

<p>We are going to allow the user the perform eight operations</p>
<ol>
<li>List suppliers</li>
<li>List products</li>
<li>Create supplier</li>
<li>Create product</li>
<li>Change product quantity</li>
<li>Delete supplier</li>
<li>Delete product</li>
<li>Exit program</li>
</ol>
<p>Of course, it could be less, for the sake of the tutorial I wanted to portrait all the basic CRUD operations (Create/Read/Update/Delete)</p>
<h1 id="the-code">The Code</h1>
<h2 id="setting-up-database">Setting up database</h2>
<p>We need to start a connection with the SQLite database, which is nothing more than a file. We can do it directly, but we are going to get the connection from the main program calling the function <code>create_connection</code> that will receive db (the file path of the database) and return the connection</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_connection</span>(<span class="hljs-params">db</span>):</span>
    conn = <span class="hljs-literal">None</span>
    <span class="hljs-keyword">try</span>:
        conn = sqlite3.connect(db)
        conn.execute(<span class="hljs-string">"PRAGMA foreign_keys = 1"</span>)
    <span class="hljs-keyword">except</span> sqlite3.Error <span class="hljs-keyword">as</span> err:
        print(err)
    <span class="hljs-keyword">return</span> conn
</code></pre><p>Now we can in the main program, call it like this</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    DBFILE = <span class="hljs-string">"db.sqlite3"</span> <span class="hljs-comment"># You can choose any name you want</span>

    conn = create_connection(DBFILE)
    <span class="hljs-keyword">with</span> conn:
         <span class="hljs-comment"># We perform operations to the database inside the with statement</span>
         <span class="hljs-comment"># It is a much readable way, and we can omit to close the connection</span>
         <span class="hljs-comment"># with can handle it</span>
</code></pre><h2 id="creating-our-tables">Creating our tables</h2>
<p>We may need to create our tables, that would be handled by the functions <code>createProducts</code> and <code>createSuppliers</code></p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">createSuppliers</span>(<span class="hljs-params">conn</span>):</span>
    query = <span class="hljs-string">"""CREATE TABLE IF NOT EXISTS suppliers (
        id INTEGER PRIMARY KEY NOT NULL,
        name TEXT NOT NULL,
        address TEXT
        );"""</span>
    execute(conn, query)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">createProducts</span>(<span class="hljs-params">conn</span>):</span>
    query = <span class="hljs-string">"""CREATE TABLE IF NOT EXISTS products (
        id INTEGER PRIMARY KEY NOT NULL,
        description TEXT NOT NULL,
        quantity INTEGER NOT NULL,
        supplier_id INTEGER NOT NULL,
        FOREIGN KEY(supplier_id) REFERENCES suppliers(id)
        );"""</span>
    execute(conn, query)
</code></pre><p>The "IF NOT EXISTS" will allow us to create them only if they already don't exist. That foreign key considers this part of the problem: <em>"Every product they have is only bought from one supplier"</em>.</p>
<p>Now, what is that <code>execute</code> function at the end? We need to code that.</p>
<pre><code>def <span class="hljs-keyword">execute</span>(<span class="hljs-keyword">conn</span>, <span class="hljs-keyword">query</span>, args = <span class="hljs-keyword">None</span>):
    <span class="hljs-keyword">if</span> args:
        conn.execute(<span class="hljs-keyword">query</span>, args)
        conn.commit()
    <span class="hljs-keyword">else</span>:
        conn.execute(<span class="hljs-keyword">query</span>)
        conn.commit()
</code></pre><p>Without this function we will be repeating the <code>conn.execute</code> and <code>conn.commit</code> every time we need to execute a query.</p>
<h2 id="inserting-data-into-our-database">Inserting data into our database</h2>
<p>So now to insert a supplier we will make a function like this</p>
<pre><code>def insertSupplier(conn, supplier):
    query = "<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> SUPPLIERS (<span class="hljs-keyword">name</span>, address) <span class="hljs-keyword">VALUES</span> (?,?);"
    <span class="hljs-keyword">execute</span>(<span class="hljs-keyword">conn</span>, <span class="hljs-keyword">query</span>, supplier)
</code></pre><p>The supplier argument should be a list with the value (name, address). See how tiny the function is? That's because we wrote <code>execute</code> and <code>create_connection</code> before. To insert a product you can follow along with that pattern.</p>
<h2 id="listing-all-the-records">Listing all the records</h2>
<p>To read every record that is stored in a table, we will use the SQL Select statement</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">selectAllProducts</span>(<span class="hljs-params">conn</span>):</span>
    query = <span class="hljs-string">"SELECT * FROM products;"</span>
    <span class="hljs-keyword">print</span> (pd.read_sql_query(query, conn))
</code></pre><p><code>pd</code> is the alias for <code>pandas</code>, a library that really helps when it comes to showing and manipulating data, we need to import it at the top of our python program like this <code>import pandas as pd</code>. The <code>read_sql_query</code> function returns a DataFrame corresponding to the result set of the query string. Think of the DataFrame as a table, a pretty formatted one.</p>
<h2 id="update-a-product">Update a product</h2>
<p>We will need to update the product's stock, so we will need a positive or negative quantity to add or subtract from the current stock.</p>
<pre><code>def updateProductQuantity(conn, productId, quantity):
    query = "<span class="hljs-keyword">UPDATE</span> products <span class="hljs-keyword">SET</span> quantity = (quantity + ?) <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">id</span> = ?;"
    <span class="hljs-keyword">execute</span>(<span class="hljs-keyword">conn</span>, <span class="hljs-keyword">query</span>, (quantity, productId))
</code></pre><h2 id="delete-a-record">Delete a record</h2>
<p>In order to delete a record, we must call the DELETE statement with the id of the object we want to remove.</p>
<pre><code>def deleteSupplier(conn, supplierId):
    query = "<span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">FROM</span> suppliers <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">id</span> = ?;"
    <span class="hljs-keyword">execute</span>(<span class="hljs-keyword">conn</span>, <span class="hljs-keyword">query</span>, supplierId)
</code></pre><div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="final-thoughts">Final thoughts</h1>
<p>Yay! You got here. We performed all the basic operations for a CRUD program. You can allow the user to interact with the previous functions in different ways. The final example will show you just a basic input menu, but you can use them within a web app, a pyqt desktop, or even a Raspberry PI!</p>
<p>Here's the final code</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="3e4b8bfaf2d3d4652c4f93371a62de8f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/marcelozarate/3e4b8bfaf2d3d4652c4f93371a62de8f" class="embed-card">https://gist.github.com/marcelozarate/3e4b8bfaf2d3d4652c4f93371a62de8f</a></div><p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div><div class="hn-embed-widget" id="three-dots-separator"></div><p>Please tell me, <em>have you ever tried SQLite? And if you have, what was the last thing you used it for?</em></p>
]]></content:encoded></item><item><title><![CDATA[How forEach can be totally useless]]></title><description><![CDATA[Good day, fellow reader.
Two weeks ago I was talking to a colleague, who has plenty of years of PHP expertise, and he was amazed by his personal discovery of the "for each" loop. 
I couldn't hide my surprise at how could that knowledge be elusive to ...]]></description><link>https://marcelozarate.com/how-foreach-can-be-totally-useless</link><guid isPermaLink="true">https://marcelozarate.com/how-foreach-can-be-totally-useless</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[newbie]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Python]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Thu, 07 Oct 2021 21:52:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633643350976/Wh-apb-xw.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader.</p>
<p>Two weeks ago I was talking to a colleague, who has plenty of years of PHP expertise, and he was amazed by his personal discovery of the "for each" loop. 
I couldn't hide my surprise at how could that knowledge be elusive to him, but after my initial reaction, that could be portrayed like this:</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632787779607/OqewIn0aX.gif" alt="kramer.gif" />
<em>Kramer from Seinfeld (TV Series)</em>
</center>

<p>I said: "well, it's useful depending on the case". He stated that many times he needed to apply the same behaviour to every page in a set of pages. And how that structure seemed more natural for him, so he was using it as much as he could. </p>
<p>That got me thinking into the real concept behind the for each loop, how can it be used, abused. I also wonder, how he could go by so many years without using it and by no means being powerless in his ability to make quality code.</p>
<p>So, what is actually a for each? It's nothing more than a for loop, that takes into consideration every item in a set of items, and applies (hopefully) some action to it.</p>
<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="for-each-features">For each features</h1>
<p><em>Disclaimer: "for each" loop may vary from language to language. </em></p>
<h2 id="traversing-items-in-a-collection">Traversing items in a collection</h2>
<p>Yeah, yeah, you got it. I just like the word traversing and wanted to include it in some text.</p>
<h2 id="it-is-a-loop-sentence">It is a loop sentence</h2>
<p>That implies two important things.</p>
<ol>
<li>Behind the scenes, usually it's written with a for loop with some perks.</li>
<li>There's nothing you can do with a foreach you could not achieve with a classic for.</li>
</ol>
<h2 id="doesnt-keep-a-reference-to-the-current-index">Doesn't keep a reference to the current index</h2>
<p>This doesn't mean you can't get the index of the current item inside a for each. It's just that it (usually) was not designed for it. Attempting that would mean extra work. From getting an index from a callback, up to finding the current element in the collection you are already iterating. It would be smarter just to use another kind of loop.</p>
<p>For each usually describes</p>
<blockquote>
<p>"Apply this action to every item" </p>
</blockquote>
<p>Instead of another kind of loops that are meant for</p>
<blockquote>
<p>"Do this x times"</p>
</blockquote>
<p>or</p>
<blockquote>
<p>"Do this for items numbered a,b,x..." </p>
</blockquote>
<h2 id="performance-for-foreach">Performance for != foreach</h2>
<p>It's not that easy for a generic article on this topic to make such a statement without proper benchmarks.
Let me just say that if your dataset is too big, or the performance in your app is critical, you should consider this. Write in the comments if you disagree or can prove me wrong.</p>
<div class="hn-embed-widget" id="three-dots-separator"></div><h1 id="code">Code</h1>
<h2 id="pseudo-code">Pseudo-code</h2>
<pre><code><span class="hljs-keyword">for</span> <span class="hljs-keyword">each</span> item <span class="hljs-keyword">in</span> collection
    // <span class="hljs-keyword">do</span> this <span class="hljs-keyword">to</span> item
</code></pre><h2 id="javascript">Javascript</h2>
<p>ES6 introduced the for...of</p>
<pre><code><span class="hljs-keyword">for</span> (<span class="hljs-built_in">let</span> book of books) {
  book.ISBN = getISBN();
}
</code></pre><p>Or the functional way</p>
<pre><code>books.<span class="hljs-keyword">forEach</span>(book =&gt; {
  book.ISBN = getISBN();
}
</code></pre><h2 id="php">PHP</h2>
<pre><code><span class="hljs-keyword">foreach</span> ($posts <span class="hljs-keyword">as</span> $post) {
    <span class="hljs-keyword">echo</span> $post-&gt;title;
    <span class="hljs-keyword">echo</span> $post-&gt;body;
}
</code></pre><h2 id="python">Python</h2>
<pre><code><span class="hljs-keyword">for</span> beer <span class="hljs-keyword">in</span> beers:
    print(beer.name)
    print(beer.IBU)
    print(beer.ABV)
</code></pre><p>The interesting thing about foreach in python, is that it actually is the standard for loop. If you want the classic <code>for (int i=0; i&lt;array.length; i++)</code></p>
<pre><code><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(<span class="hljs-keyword">array</span>)):
    # <span class="hljs-keyword">Do</span> whatever <span class="hljs-keyword">with</span> i <span class="hljs-keyword">as</span> <span class="hljs-keyword">index</span>
</code></pre><p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div><div class="hn-embed-widget" id="three-dots-separator"></div><p>So tell me, do you find for each loop useful? In which language do you use it?</p>
]]></content:encoded></item><item><title><![CDATA[The start of a writing journey]]></title><description><![CDATA[Good day, fellow reader. And I say fellow because we have something in common: we are both voracious readers. It's a separate tale of how that turned into writing for me.
My name is Marcelo Zárate. I'm an Argentine father, spouse, and developer. I'm ...]]></description><link>https://marcelozarate.com/the-start-of-a-writing-journey</link><guid isPermaLink="true">https://marcelozarate.com/the-start-of-a-writing-journey</guid><category><![CDATA[first post]]></category><category><![CDATA[introduction]]></category><category><![CDATA[writing]]></category><dc:creator><![CDATA[Marcelo Zárate]]></dc:creator><pubDate>Sun, 03 Oct 2021 01:18:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632871152605/AESuAT4jA.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Good day, fellow reader. And I say fellow because we have something in common: we are both voracious readers. It's a separate tale of how that turned into writing for me.</p>
<p>My name is Marcelo Zárate. I'm an Argentine father, spouse, and developer. I'm interested in a variety of languages and technologies. I'm always excited to discover anything new.</p>
<p>A few days ago I heard at a seminar that the <em>"What for"</em> in our daily planner should take precedence over the <em>"Why"</em> So I'm going to try to put this thought into practice right now.</p>
<p>There are mainly 3 reasons that I started this journey <em>(What for?)</em></p>
<h1 id="putting-my-capacity-to-be-consistent-to-the-test">Putting my capacity to be consistent to the test 📝</h1>
<p>Working on a non-dev job, I managed to make at least one useful commit per week for the last year. That was a real challenge but proved myself I could be consistent. Going to try the same for writing (1 article per week should do).</p>
<h1 id="learning">Learning 👨‍🏫</h1>
<p>Being a teacher for kids in the past taught me one valuable lesson: </p>
<blockquote>
<p>If you want to be certain you know something, go ahead and teach it.</p>
</blockquote>
<p>You can confirm you knew the subject. You can also learn by attempting to prepare a class on a topic you thought you already knew about.</p>
<h1 id="improve-my-english">Improve my English 🗽</h1>
<p>Being a non-native English speaker, I found it almost natural to read technical stuff in English. Writing seems to be a different level of difficulty, but I'm confident it will help me step up and reach a larger audience.</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632870577745/68krOLNSR.webp" alt="lisawecanbetterourselves.webp" /><em>It's not easy, because writing requires research, planning, confidence, and a magic spark.</em>
</center>

<p>Are you planning on writing too? You can do it! Start your own blog now with <a target="_blank" href="https://hashnode.com/@marcelozarate/joinme">Hashnode</a> 
I really took time researching all the options, and I found Hashnode to be a solid platform. Shoutout to <a class="user-mention" href="https://hashnode.com/@sandeep">Sandeep Panda</a>!</p>
<p>See you around!</p>
<div class="hn-embed-widget" id="ctafollow"></div><hr />
<p>Cover photo by <a href="https://unsplash.com/@linalitvina?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Angelina Litvin</a> on <a href="https://unsplash.com/s/photos/writing?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
]]></content:encoded></item></channel></rss>