<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Víctor Adrián</title>
    <description>The latest articles on DEV Community by Víctor Adrián (@lobo_tuerto).</description>
    <link>https://dev.to/lobo_tuerto</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F54783%2F90d55e1e-e28c-4fa8-90e0-5cb6954fbda8.jpeg</url>
      <title>DEV Community: Víctor Adrián</title>
      <link>https://dev.to/lobo_tuerto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lobo_tuerto"/>
    <language>en</language>
    <item>
      <title>How to enable night mode for Calibre in Manjaro Linux</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Sat, 08 Dec 2018 16:19:06 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/how-to-enable-night-mode-for-calibre-in-manjaro-linux-204b</link>
      <guid>https://dev.to/lobo_tuerto/how-to-enable-night-mode-for-calibre-in-manjaro-linux-204b</guid>
      <description>

&lt;p&gt;&lt;strong&gt;Manjaro Linux i3&lt;/strong&gt; ships with a dark theme setting by default.&lt;br&gt;&lt;br&gt;
Something I really appreciate.&lt;/p&gt;

&lt;p&gt;When you install &lt;strong&gt;Calibre&lt;/strong&gt; and execute it, you’ll find thatit doesn’t use the system’s theme.&lt;br&gt;&lt;br&gt;
However, telling it to do so is really easy.&lt;/p&gt;

&lt;p&gt;You just need to set the &lt;code&gt;CALIBRE_USE_SYSTEM_THEME&lt;/code&gt; env var, like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e '\nexport CALIBRE_USE_SYSTEM_THEME=1' &amp;gt;&amp;gt; .profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To try it out immediately, export the &lt;code&gt;CALIBRE_USE_SYSTEM_THEME&lt;/code&gt; var and launch &lt;strong&gt;Calibre&lt;/strong&gt; with:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CALIBRE_USE_SYSTEM_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
calibre&amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want it to work through &lt;code&gt;d-menu&lt;/code&gt; (SUPER + D) &lt;em&gt;logout&lt;/em&gt; and &lt;em&gt;login&lt;/em&gt; backinto session.&lt;/p&gt;

&lt;p&gt;That’s it!&lt;/p&gt;


</description>
      <category>manjaro</category>
      <category>i3</category>
      <category>calibre</category>
      <category>nightmode</category>
    </item>
    <item>
      <title>How to fix Redshift in Manjaro Linux i3</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Thu, 04 Oct 2018 02:11:59 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/how-to-fix-redshift-in-manjaro-linux-i3-3i6k</link>
      <guid>https://dev.to/lobo_tuerto/how-to-fix-redshift-in-manjaro-linux-i3-3i6k</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/jonls/redshift" rel="noopener noreferrer"&gt;Redshift&lt;/a&gt; is a very cool program that can help in keeping your eyesight healthy — it’ll tint your screen red a little bit when the night approaches.&lt;/p&gt;

&lt;p&gt;This puts less strain in your eyes.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;Everything was working good, I had the &lt;code&gt;redshift&lt;/code&gt; package installed and had setup it to start automatically on my &lt;code&gt;~/.i3/config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It was just after an update that I started to see this when trying to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trying location provider `geoclue2'...
Using provider `geoclue2'.
Using method `randr'.
Waiting for initial location to become available...
Unable to start GeoClue client:
 GDBus.Error:org.freedesktop.DBus.Error.NoReply:
 Message recipient disconnected from message bus without replying.
Unable to get location from provider.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And seeing this dialog when trying to start &lt;code&gt;redshift-gtk&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fhow-to-fix-redshift-in-manjaro-linux-i3%2Fredshift-gtk-error.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fhow-to-fix-redshift-in-manjaro-linux-i3%2Fredshift-gtk-error.png" alt="redshift-gtk error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It never worked after that, even with the newest versions for &lt;code&gt;geoclue2&lt;/code&gt; and &lt;code&gt;redshift&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pacman -Q geoclue2 redshift
geoclue2 2.4.12-1
redshift 1.12-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The solution
&lt;/h1&gt;

&lt;p&gt;After doing some sleuthing, I found a solution.&lt;/p&gt;

&lt;p&gt;Edit your &lt;code&gt;/etc/geoclue/geoclue.conf&lt;/code&gt; file, and add this at the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ...
[redshift]
allowed=true
system=false
users=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start &lt;strong&gt;Redshift&lt;/strong&gt; automatically, add these lines to your &lt;code&gt;~/.i3/config&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exec --no-startup-id /usr/lib/geoclue-2.0/demos/agent
exec --no-startup-id redshift-gtk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it!&lt;/p&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/jonls/redshift" rel="noopener noreferrer"&gt;Redshift&lt;/a&gt; — Redshift adjusts the color temperature of your screen according to your surroundings.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/index.php/Redshift" rel="noopener noreferrer"&gt;ArchWiki – Redshift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jonls/redshift/issues/636" rel="noopener noreferrer"&gt;redshift disallowed from using GeoClue&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>manjaro</category>
      <category>troubleshooting</category>
      <category>redshift</category>
      <category>i3</category>
    </item>
    <item>
      <title>How to create a Manjaro Linux live USB through the CLI</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Sat, 22 Sep 2018 04:39:12 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/how-to-create-a-manjaro-linux-live-usb-through-the-cli-453l</link>
      <guid>https://dev.to/lobo_tuerto/how-to-create-a-manjaro-linux-live-usb-through-the-cli-453l</guid>
      <description>

&lt;p&gt;You can check the latest updated version of this article at &lt;a href="https://lobotuerto.com/blog/how-to-create-a-manjaro-linux-live-usb-through-the-cli/"&gt;lobotuerto's notes - How to create a Manjaro Linux live USB through the CLI.&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Download the Manjaro i3 community edition
&lt;/h1&gt;

&lt;p&gt;Talking about &lt;strong&gt;Manjaro&lt;/strong&gt; I prefer the &lt;strong&gt;i3&lt;/strong&gt; community edition.&lt;/p&gt;

&lt;p&gt;Be sure to have an &lt;code&gt;.iso&lt;/code&gt; file ready, or download the latest image from &lt;a href="https://manjaro.org/community-editions/"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Verify with SHA1 or SHA256
&lt;/h1&gt;

&lt;p&gt;After you download the &lt;code&gt;.iso&lt;/code&gt; file, you can also download the &lt;code&gt;.sha1&lt;/code&gt; or &lt;code&gt;.sha256&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;To verify the &lt;strong&gt;ISO&lt;/strong&gt; against them, you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sha1sum -c manjaro-i3-17.1.12-stable-x86_64.iso.sha1
sha256sum -c manjaro-i3-17.1.12-stable-x86_64.iso.sha256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is allright, you’ll see: &lt;code&gt;manjaro-i3-17.1.12-stable-x86_64.iso: OK&lt;/code&gt;for both of them.&lt;/p&gt;

&lt;h1&gt;
  
  
  Find the right letter for your device
&lt;/h1&gt;

&lt;p&gt;Insert the stick into a port and get a list of connected devices with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo fdisk -l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identify the letter for your drive on the output, in my case the drive I’m looking for is this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Disk /dev/sdc: 14.3 GiB, 15376318464 bytes, 30031872 sectors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;I can tell because it’s —supposedly— a 16GB device, look at the &lt;strong&gt;14.3 GiB&lt;/strong&gt; size reported above.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this example, the letter for the drive is the &lt;code&gt;c&lt;/code&gt; from &lt;code&gt;sdc&lt;/code&gt;. It could have been &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt; or something else. Just &lt;strong&gt;make sure&lt;/strong&gt; that it is indeed the drive you want to trash.&lt;br&gt;&lt;br&gt;
You won’t be able to recover anything from it once it’s been &lt;em&gt;zeroed.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Zero the bits out of the USB drive
&lt;/h1&gt;

&lt;p&gt;Next, let’s &lt;em&gt;zero&lt;/em&gt; the drive out, this serves as a security measure and also it allows you to tell ifthe drive is still functioning well —if the drive is dying, the process will take an unusually long time, or it’ll get stuck before reaching the end, that’s a sign that you need to get a new USB.&lt;/p&gt;

&lt;p&gt;Ok, let’s write zeros all over the USB drive with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dd if=/dev/zero of=/dev/sdc bs=4M status=progress conv=fdatasync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Remember that the command above is considering that the USB is located at: &lt;code&gt;/dev/sdc&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Make sure you have the right path for yours!&lt;/p&gt;

&lt;p&gt;That command will report progress back to you.&lt;/p&gt;
&lt;h1&gt;
  
  
  Copy the ISO image to the USB drive
&lt;/h1&gt;

&lt;p&gt;When finished, go to the directory where you downloaded the &lt;strong&gt;.iso&lt;/strong&gt; file and deploy it to the USB drive like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dd if=manjaro-i3-17.1.12-stable-x86_64.iso of=/dev/sdc bs=4M \
status=progress conv=fdatasync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it, now you should have a bootable USB with &lt;strong&gt;Manjaro Linux&lt;/strong&gt; in it!&lt;/p&gt;

</description>
      <category>manjaro</category>
      <category>usb</category>
      <category>cli</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Basic Git configuration</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Mon, 11 Jun 2018 00:20:33 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/basic-git-configuration-5545</link>
      <guid>https://dev.to/lobo_tuerto/basic-git-configuration-5545</guid>
      <description>

&lt;p&gt;You can check the latest updated version of this article at &lt;a href="https://lobotuerto.com/blog/basic-git-configuration/"&gt;lobotuerto's notes - Basic Git configuration.&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;If you are a &lt;strong&gt;Manjaro Linux&lt;/strong&gt; user, then you already have &lt;strong&gt;Git&lt;/strong&gt; in your machine.&lt;/p&gt;

&lt;p&gt;If you are an &lt;strong&gt;Ubuntu&lt;/strong&gt; user, install it with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;You can check it's working with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# git version 2.17.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s proceed with some basic setup, so we are able to initialize new projects and make commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  User and email
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt; will use this data to &lt;em&gt;mark&lt;/em&gt; any commits you create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Your name goes here"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"your@email.goes.here"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Colorful CLI
&lt;/h2&gt;

&lt;p&gt;To have colored output when doing &lt;code&gt;git status&lt;/code&gt; and &lt;code&gt;git diff&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; color.ui &lt;span class="s2"&gt;"auto"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  CPU threads
&lt;/h2&gt;

&lt;p&gt;To enable automatic detection of CPU threads to use for packing repositories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; pack.threads &lt;span class="s2"&gt;"0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Useful alias
&lt;/h2&gt;

&lt;p&gt;Add this to your &lt;code&gt;~/.gitconfig&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    l &lt;span class="o"&gt;=&lt;/span&gt; log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--decorate&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;

    ll &lt;span class="o"&gt;=&lt;/span&gt; log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--abbrev-commit&lt;/span&gt; &lt;span class="nt"&gt;--decorate&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;relative &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) \
    %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)'&lt;/span&gt;

    lll &lt;span class="o"&gt;=&lt;/span&gt; log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--abbrev-commit&lt;/span&gt; &lt;span class="nt"&gt;--decorate&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;relative &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) \
    %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--branches&lt;/span&gt;

    co &lt;span class="o"&gt;=&lt;/span&gt; checkout
    ci &lt;span class="o"&gt;=&lt;/span&gt; commit
    man &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;help
    &lt;/span&gt;h &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;help
    &lt;/span&gt;a &lt;span class="o"&gt;=&lt;/span&gt; add
    f &lt;span class="o"&gt;=&lt;/span&gt; fetch
    d &lt;span class="o"&gt;=&lt;/span&gt; diff
    dc &lt;span class="o"&gt;=&lt;/span&gt; diff &lt;span class="nt"&gt;--cached&lt;/span&gt;
    dt &lt;span class="o"&gt;=&lt;/span&gt; difftool
    dtc &lt;span class="o"&gt;=&lt;/span&gt; difftool &lt;span class="nt"&gt;--cached&lt;/span&gt;
    ds &lt;span class="o"&gt;=&lt;/span&gt; diff &lt;span class="nt"&gt;--stat&lt;/span&gt;
    dsc &lt;span class="o"&gt;=&lt;/span&gt; diff &lt;span class="nt"&gt;--stat&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt;
    s &lt;span class="o"&gt;=&lt;/span&gt; status &lt;span class="nt"&gt;--short&lt;/span&gt; &lt;span class="nt"&gt;--branch&lt;/span&gt;
    b &lt;span class="o"&gt;=&lt;/span&gt; branch

&lt;span class="o"&gt;[&lt;/span&gt;credential]
    helper &lt;span class="o"&gt;=&lt;/span&gt; cache

&lt;span class="o"&gt;[&lt;/span&gt;diff]
    algorithm &lt;span class="o"&gt;=&lt;/span&gt; patience
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Global .gitignore
&lt;/h2&gt;

&lt;p&gt;Let’s define a global &lt;strong&gt;.gitignore&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; core.excludesfile ~/.gitignore_global
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let’s use it to ignore &lt;strong&gt;Visual Studio Code&lt;/strong&gt; project files and also files generatedby the &lt;strong&gt;ElixirLS&lt;/strong&gt; plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".vscode/"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gitignore_global
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".elixir_ls/"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gitignore_global
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dealing with line endings
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Linux / Mac
&lt;/h3&gt;

&lt;p&gt;If you are a &lt;strong&gt;Linux / Mac&lt;/strong&gt; user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; core.autocrlf input
git config &lt;span class="nt"&gt;--global&lt;/span&gt; core.safecrlf &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Windows
&lt;/h3&gt;

&lt;p&gt;If you are a &lt;strong&gt;Windows&lt;/strong&gt; user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; core.autocrlf &lt;span class="nb"&gt;true
&lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; core.safecrlf &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://try.github.com/"&gt;Got 15 minutes and want to learn Git?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gitimmersion.com/"&gt;A Guided Tour through the Fundamentals of Git (tutorial)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book"&gt;Pro Git by Scott Chacon (libro)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marklodato.github.com/visual-git-guide/index-en.html"&gt;A visual Git reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jonas.nitro.dk/git/quick-reference.html"&gt;Git Quick Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html"&gt;Git for everyone&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced use cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lobotuerto.com/blog/how-to-setup-your-own-private-git-repositories-with-gitolite/"&gt;How to setup your own private Git repositories with Gitolite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lobotuerto.com/blog/how-to-setup-automatic-hugo-website-generation-and-deployment-with-git/"&gt;How to setup automatic Hugo website generation and deployment with Git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hosted services
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sitaramc/gitolite"&gt;gitolite&lt;/a&gt; (self-hosted)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bitbucket.org/"&gt;Bitbucket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://about.gitlab.com/"&gt;GitLab&lt;/a&gt; (can be self-hosted)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>productivity</category>
      <category>terminal</category>
      <category>setup</category>
    </item>
    <item>
      <title>A little critique of Google's Material Design and its associated websites</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Mon, 07 May 2018 06:00:00 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/a-little-critique-of-googles-material-design-and-its-associated-websites-2kk5</link>
      <guid>https://dev.to/lobo_tuerto/a-little-critique-of-googles-material-design-and-its-associated-websites-2kk5</guid>
      <description>

&lt;p&gt;You can check the latest updated version of this article at &lt;a href="https://lobotuerto.com/blog/a-little-critique-of-google-material-design-and-its-associated-websites/" rel="noopener noreferrer"&gt;lobotuerto's notes - A little critique of Google's Material Design and its associated websites.&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I have a couple of opinions to state regarding the spec —which by the way I think is a &lt;strong&gt;great&lt;/strong&gt; design specification— and its accompanying websites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://material.io/guidelines/" rel="noopener noreferrer"&gt;material.io/guidelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://material.io/icons/" rel="noopener noreferrer"&gt;material.io/icons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Guidelines on toggle functionality
&lt;/h1&gt;

&lt;p&gt;I think regarding toggles, you should pick one way to get your point across to the user.&lt;br&gt;&lt;br&gt;
And be consistent about it, do not send mixed signals.&lt;/p&gt;

&lt;p&gt;Here is a couple of examples that shows —in my view— incongruent behaviour:&lt;/p&gt;
&lt;h2&gt;
  
  
  Expansion panels
&lt;/h2&gt;

&lt;p&gt;For &lt;a href="https://material.io/guidelines/components/expansion-panels.html" rel="noopener noreferrer"&gt;expansion panels&lt;/a&gt; —or lists, the icon (&lt;code&gt;arrow_drop_up&lt;/code&gt;/&lt;code&gt;arrow_drop_down&lt;/code&gt;) doesn’t represent the state of the panel, but the intent of the user —what will happen if I press on it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fa-little-critique-of-google-material-design-and-its-associated-websites%2Fcomponents-expansion-panels.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fa-little-critique-of-google-material-design-and-its-associated-websites%2Fcomponents-expansion-panels.png" alt="Components Expansion Panels"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the guidelines examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When &lt;strong&gt;closed,&lt;/strong&gt; you should show an arrow down, signaling the user that if they press on it it’ll expand.&lt;/li&gt;
&lt;li&gt;When &lt;strong&gt;opened,&lt;/strong&gt; you should show an arrow up, signaling the user that pressing on it will close the expanded panel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here, the visual cue ( &lt;strong&gt;the arrow&lt;/strong&gt; ) represents &lt;strong&gt;intent&lt;/strong&gt; , not state.&lt;/p&gt;
&lt;h2&gt;
  
  
  Password redaction
&lt;/h2&gt;

&lt;p&gt;On &lt;a href="https://material.io/guidelines/components/text-fields.html#text-fields-input-types" rel="noopener noreferrer"&gt;password redaction&lt;/a&gt; it’s the other way around:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fa-little-critique-of-google-material-design-and-its-associated-websites%2Fpassword1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fa-little-critique-of-google-material-design-and-its-associated-websites%2Fpassword1.png" alt="Shown password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fa-little-critique-of-google-material-design-and-its-associated-websites%2Fpassword2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flobotuerto.com%2Fblog%2Fa-little-critique-of-google-material-design-and-its-associated-websites%2Fpassword2.png" alt="Hidden password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the guidelines examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the eye is &lt;strong&gt;open&lt;/strong&gt; the password is shown. This is only showing the state of the thing in cuestion.&lt;/li&gt;
&lt;li&gt;When the eye is &lt;strong&gt;closed&lt;/strong&gt; the password is “hidden”. Again, this is showing the state of the component, instead of intent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here, the visual cue ( &lt;strong&gt;the eye&lt;/strong&gt; ) represents &lt;strong&gt;state&lt;/strong&gt; , not intent.&lt;/p&gt;
&lt;h2&gt;
  
  
  Switch buttons
&lt;/h2&gt;

&lt;p&gt;On the other hand, switches are great toggling controls because what they do is show &lt;strong&gt;state&lt;/strong&gt; and &lt;strong&gt;intent&lt;/strong&gt; towards whatever label they have associated.&lt;/p&gt;

&lt;p&gt;So here, it’s really up to the developer to find great labels for a great UX.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;o--&amp;gt; Crushing it! (this is off, meaning we are not crushing it)
&amp;lt;--o&amp;gt; Crushing it! (this is on, meaning we are crushing it now)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Pardon my ASCII art…)&lt;/p&gt;

&lt;p&gt;It helps a great deal that the switch makes use of the spec and clearly signals the user when it’s &lt;strong&gt;on.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intent vs state
&lt;/h2&gt;

&lt;p&gt;Design languages or specifications should be coherent as a whole.&lt;br&gt;&lt;br&gt;
Some questions that arose from the observations above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should icons show &lt;strong&gt;state&lt;/strong&gt; or &lt;strong&gt;intent&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Should stuff like this be clearly documented in the spec?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the second question I think the answer should be &lt;strong&gt;yes&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
As for the first one, &lt;strong&gt;Material Design&lt;/strong&gt; should go one way or the other, not both, nor keep it undefined.&lt;/p&gt;

&lt;h3&gt;
  
  
  My resolution
&lt;/h3&gt;

&lt;p&gt;In my view, taking in consideration the spec’s spirit, the way to go would be for icons to signal &lt;strong&gt;intent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another less subjective reason to go this way is that showing &lt;strong&gt;intent&lt;/strong&gt; allows&lt;br&gt;
for a series of actions to be chained using one changing icon —whether you should be doing this or not is debatable, the points is that you can— since you are always letting the user know what comes next if they click on it.&lt;/p&gt;

&lt;p&gt;You can’t convey this information using icons to show &lt;strong&gt;state,&lt;/strong&gt; since the next state can’t be known by looking at the icon alone, you can only know what the present state is.&lt;/p&gt;

&lt;p&gt;Nonetheless, using &lt;em&gt;non-actionable&lt;/em&gt; icons to present state is OK.&lt;/p&gt;

&lt;p&gt;In the end what I mean is:&lt;/p&gt;

&lt;p&gt;Keep the &lt;strong&gt;expansion panels&lt;/strong&gt; the way they are now, and change how the &lt;strong&gt;password redaction&lt;/strong&gt; icons work (just swap the icons out).&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Switch&lt;/strong&gt; buttons are good as they are.&lt;/p&gt;




&lt;p&gt;I know this subject is a tough one. It’s been discussed for ages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jef Raskin&lt;/strong&gt; was writing about this issue quite a few years ago in&lt;a href="https://www.amazon.com/Humane-Interface-Directions-Designing-Interactive/dp/0201379376" rel="noopener noreferrer"&gt;The Humane Interface: New Directions for Designing Interactive Systems&lt;/a&gt;, an &lt;strong&gt;Addison-Wesley Professional&lt;/strong&gt; publication from April 8th, 2000.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alan Cooper&lt;/strong&gt; also discusses this in his book&lt;a href="https://www.amazon.com/About-Face-Essentials-Interaction-Design/dp/1118766571" rel="noopener noreferrer"&gt;About Face: The Essentials of Interaction Design&lt;/a&gt;published by &lt;strong&gt;Wiley&lt;/strong&gt; on September 2nd, 2014 (looks like the firs edition is from August 25th, 1995):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Flip-flop button controls are very efficient. They save space by controlling two mutually exclusive options with a single control. The problem with flip-flop controls is that they fail to fulfill the second duty of every control - to inform the user of their current state. If the button says ON when the state is off, it is unclear what the setting is. If it is OFF when the state is off, however, where is the ON button? Don’t use them. Not on buttons and no on menus!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is a good amount of discussion about this subject &lt;a href="https://ux.stackexchange.com/questions/1318/should-a-toggle-button-show-its-current-state-or-the-state-to-which-it-will-chan" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://ux.stackexchange.com/questions/20713/toggle-buttons-turn-on-vs-enable" rel="noopener noreferrer"&gt;here&lt;/a&gt; on &lt;a href="https://ux.stackexchange.com/" rel="noopener noreferrer"&gt;StackExchange UX&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Websites
&lt;/h1&gt;

&lt;p&gt;Now let’s talk about a couple of websites related to &lt;strong&gt;Material Design,&lt;/strong&gt; and some annoyances —&lt;em&gt;bad&lt;/em&gt; UX; AKA UX &lt;em&gt;opportunity areas&lt;/em&gt;— I’ve found while using them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Material Design guidelines
&lt;/h2&gt;

&lt;p&gt;Pages on the &lt;a href="https://material.io/guidelines/" rel="noopener noreferrer"&gt;Material Design guidelines&lt;/a&gt; should include anchors on section headers for easy linking. It’s so annoying that they don’t!&lt;/p&gt;

&lt;p&gt;A good solution would be to have anchors show when hovering section headers, subheaders or titles.&lt;/p&gt;

&lt;p&gt;Trying to be too &lt;strong&gt;Material Design&lt;/strong&gt; at the cost of good &lt;strong&gt;UX&lt;/strong&gt; —or convenience— is not good.&lt;/p&gt;

&lt;p&gt;Case in point: I couldn’t link to the &lt;strong&gt;password redaction&lt;/strong&gt; section, because there is no anchor for it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Material Design icons
&lt;/h2&gt;

&lt;p&gt;I find a little frustrating that icons that are basically the same as others, don’t show their aliases.&lt;/p&gt;

&lt;p&gt;For example, these are the same icons but you have to find out for yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;color_lens&lt;/code&gt;, &lt;code&gt;palette&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create&lt;/code&gt;, &lt;code&gt;mode_edit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;block&lt;/code&gt;, &lt;code&gt;do_not_disturb_alt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;And more...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I get that it must be in the interest of semantics, but believe me, users —like me— end up using icons that look like &lt;em&gt;what we need,&lt;/em&gt; not &lt;em&gt;what they are named as.&lt;/em&gt; We use names to search for them.&lt;/p&gt;

&lt;p&gt;If I need a fricking circle icon for displaying a user status be sure I’ll end up using a fricking&lt;code&gt;fiber_manual_record&lt;/code&gt; icon!&lt;/p&gt;

&lt;p&gt;I find really irritating that &lt;code&gt;CTRL + F&lt;/code&gt; doesn’t work because icons are dynamically loaded into the page. So you have to use the website’s own search bar for that.&lt;/p&gt;

&lt;p&gt;If &lt;a href="https://fontawesome.com/" rel="noopener noreferrer"&gt;FontAwesome&lt;/a&gt; is doing just fine showing all their &lt;a href="https://fontawesome.com/icons" rel="noopener noreferrer"&gt;2,791 icons&lt;/a&gt; I think you’ll do just fine showing 900+.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I think my biggest criticism is that sometimes it looks like &lt;strong&gt;Material Design&lt;/strong&gt; principles are applied at the expense of good &lt;strong&gt;UX,&lt;/strong&gt; when it should be the other way around: &lt;strong&gt;UX&lt;/strong&gt; should come in first, maybe at the expense of &lt;strong&gt;Material Design.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Ideally, &lt;strong&gt;Material Design&lt;/strong&gt; should reach a point where this trade-off should never come to be.&lt;/p&gt;

&lt;h1&gt;
  
  
  2018/05/08 update
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Google&lt;/strong&gt; has just updated its &lt;strong&gt;Material Design spec,&lt;/strong&gt; and some of the links and commentary I provided above don't apply anymore. Nonetheless, I'll leave them there for history's sake.&lt;/p&gt;

&lt;p&gt;Check out the set of improvements and new guidelines they provide on their site: &lt;a href="https://material.io/design/" rel="noopener noreferrer"&gt;material.io/design&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another good thing is that we have a usable &lt;strong&gt;Material Design icons&lt;/strong&gt; site now!&lt;br&gt;
Go, check it out: &lt;a href="https://material.io/tools/icons/" rel="noopener noreferrer"&gt;material.io/icons&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>ux</category>
      <category>materialdesign</category>
    </item>
    <item>
      <title>Elixir and my ISO-8859-1 character encoding problem</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Wed, 25 Apr 2018 17:03:31 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/elixir-and-my-iso-8859-1-character-encoding-problem-5dpa</link>
      <guid>https://dev.to/lobo_tuerto/elixir-and-my-iso-8859-1-character-encoding-problem-5dpa</guid>
      <description>

&lt;p&gt;You can check the latest updated version of this article at &lt;a href="https://lobotuerto.com/blog/elixir-and-my-iso-8859-1-character-encoding-problem/"&gt;lobotuerto's notes - Elixir and my ISO-8859-1 character encoding problem.&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Being from &lt;strong&gt;México,&lt;/strong&gt; I have been wrestling with character encoding issues for a long time, in several languages…&lt;/p&gt;

&lt;p&gt;Now, it’s &lt;strong&gt;Elixir’s&lt;/strong&gt; time.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;When working my way through &lt;a href="https://www.manning.com/books/the-little-elixir-and-otp-guidebook"&gt;The little Elixir &amp;amp; OTP guidebook&lt;/a&gt; —a highly recommended one— I got stuck at the &lt;strong&gt;ID3&lt;/strong&gt; parser example program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;ID3Parser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mp3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;mp3_byte_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;byte_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp3_byte_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;id3_tag&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mp3&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"TAG"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;_rest&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id3_tag&lt;/span&gt;

        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;

      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Couldn't open &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Using &lt;a href="https://www.clementine-player.org/"&gt;Clementine&lt;/a&gt; I edited the &lt;strong&gt;ID3&lt;/strong&gt; tags for a file named&lt;code&gt;some-song.mp3&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
And put &lt;code&gt;Éso&lt;/code&gt; as its &lt;code&gt;title&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I wanted to know if the program would handle those just fine. It did not.&lt;/p&gt;



&lt;p&gt;It was all right when the &lt;strong&gt;ID3&lt;/strong&gt; tags contained only valid &lt;a href="https://ascii.cl/"&gt;ASCII characters&lt;/a&gt;, as soon as I put an &lt;em&gt;accented character&lt;/em&gt; in the &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;artist&lt;/code&gt; or &lt;code&gt;album&lt;/code&gt; what I got was an error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;ID3Parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="s2"&gt;"some-song.mp3"&lt;/span&gt;

&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ArgumentError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stdlib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;:io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_chars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:standard_io&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:unicode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;89&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The solution
&lt;/h1&gt;

&lt;p&gt;After some research &lt;a href="http://taglib.org/api/classTagLib_1_1ID3v1_1_1StringHandler.html"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/clementine-player/clementine/issues/254"&gt;there&lt;/a&gt;, then some &lt;a href="https://github.com/elixir-lang/elixir/issues/7599"&gt;error reporting&lt;/a&gt;… I found out that &lt;strong&gt;ID3v1&lt;/strong&gt; tags —the ones the program is trying to parse— should in theory be encoded as &lt;strong&gt;ISO-8859-1,&lt;/strong&gt; also known as &lt;code&gt;Latin 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What I needed was &lt;a href="http://erlang.org/doc/man/unicode.html#characters_to_binary-3"&gt;a way&lt;/a&gt; to convert those bytes from &lt;strong&gt;ISO-5589-1&lt;/strong&gt; (Latin 1) to &lt;strong&gt;UTF-8&lt;/strong&gt; (Unicode), and give &lt;code&gt;IO.puts&lt;/code&gt; something it could print without problems.&lt;/p&gt;

&lt;p&gt;I found exactly that in this &lt;strong&gt;Erlang&lt;/strong&gt; facility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="ss"&gt;:unicode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;characters_to_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;your_string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:latin1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the final program that correctly parses &lt;strong&gt;ID3v1&lt;/strong&gt; tags in their expected encoding —careful, the encoding is expected, but in no way guaranteed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;ID3Parser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mp3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;mp3_byte_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;byte_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp3_byte_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;id3_tag&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mp3&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"TAG"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;_rest&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id3_tag&lt;/span&gt;

        &lt;span class="n"&gt;to_convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_convert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;from_latin1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;

      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Couldn't open &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;from_latin1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:unicode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;characters_to_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:latin1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully this will help someone else in the same predicament.&lt;/p&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elixir-lang.org/getting-started/binaries-strings-and-char-lists.html"&gt;elixir: Binaries, strings, and charlists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simple.wikipedia.org/wiki/Mojibake"&gt;The mojibake problem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elixir</category>
      <category>programming</category>
      <category>troubleshooting</category>
      <category>unicode</category>
    </item>
    <item>
      <title>Building a JSON API with Phoenix 1.3 and Elixir</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Fri, 06 Apr 2018 18:00:00 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/building-a-json-api-with-phoenix-13-and-elixir-ooo</link>
      <guid>https://dev.to/lobo_tuerto/building-a-json-api-with-phoenix-13-and-elixir-ooo</guid>
      <description>

&lt;p&gt;You can check the latest updated version of this article at &lt;a href="https://lobotuerto.com/blog/building-a-json-api-with-phoenix-and-elixir/"&gt;lobotuerto's notes - Building a JSON API with Phoenix 1.3 and Elixir.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also includes a content table for easy navigation over there. ;)&lt;/p&gt;




&lt;p&gt;Do you have a &lt;strong&gt;Rails&lt;/strong&gt; background?&lt;/p&gt;

&lt;p&gt;Are you tired of looking at &lt;em&gt;outdated&lt;/em&gt; or &lt;em&gt;incomplete&lt;/em&gt; tutorials on how to build a &lt;strong&gt;JSON API&lt;/strong&gt; using &lt;strong&gt;Elixir&lt;/strong&gt; and &lt;strong&gt;Phoenix?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then, &lt;strong&gt;read on my friend!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;I have found there are mainly two types of tutorials one should write:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Focused, scoped tutorials.&lt;/li&gt;
&lt;li&gt;Full step-by-step tutorials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scoped, focused tutorials, should be used to explain techniques, like this one: &lt;a href="https://lobotuerto.com/blog/fluid-svgs-with-vuejs/"&gt;Fluid SVGs with Vue.js.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, fully-integrated tutorials should be used to teach about new tech stacks.&lt;/p&gt;

&lt;p&gt;Going from &lt;em&gt;zero&lt;/em&gt; to &lt;em&gt;fully working prototype&lt;/em&gt; without skipping steps.&lt;br&gt;&lt;br&gt;
With best practices baked-in, presenting the best libreries available for a given task.&lt;br&gt;&lt;br&gt;
I really like tutorials that take this &lt;em&gt;holistic&lt;/em&gt; approach.&lt;/p&gt;

&lt;p&gt;So, this won’t just be about how to generate a new Phoenix &lt;strong&gt;API only&lt;/strong&gt; app. That’s easy enough, you just need to pass the &lt;code&gt;--no-brunch --no-html&lt;/code&gt;to &lt;code&gt;mix phx.new&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This tutorial is about creating a small, but fully operational JSON API for web applications.&lt;/p&gt;



&lt;p&gt;To complement your &lt;strong&gt;API,&lt;/strong&gt; I recommend &lt;strong&gt;Vue.js&lt;/strong&gt; on the frontend:&lt;br&gt;
&lt;a href="https://lobotuerto.com/blog/quickstart-guide-for-a-new-vuejs-project/"&gt;Quickstart guide for a new Vue.js project.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;What we’ll do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new API-only Phoenix application —skip HTML and JS stuff.&lt;/li&gt;
&lt;li&gt;Create a User schema module (model) and hash its password —because storing plain text passwords in the database is just &lt;strong&gt;wrong.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Create a Users endpoint —so you can get a list of, create or delete users!&lt;/li&gt;
&lt;li&gt;CORS configuration —so you can use that frontend of yours that runs on another port / domain.&lt;/li&gt;
&lt;li&gt;Create a Sign in endpoint —using session based authentication.
I can do a &lt;strong&gt;JWT&lt;/strong&gt; one later if enough people are interested.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Let me be clear about something…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m just starting with &lt;strong&gt;Elixir / Phoenix,&lt;/strong&gt; if there are any omissions or bad practices, bear with me, notify me and I’ll fix them ASAP.&lt;/p&gt;

&lt;p&gt;This is the tutorial I wish I had available when I was trying to learn about how to implement a &lt;strong&gt;JSON API&lt;/strong&gt; with Elixir / Phoenix, but I digress.&lt;/p&gt;


&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Install Elixir
&lt;/h2&gt;

&lt;p&gt;We will start by installing &lt;strong&gt;Erlang&lt;/strong&gt; and &lt;strong&gt;Elixir&lt;/strong&gt; using the &lt;a href="https://github.com/asdf-vm/asdf"&gt;asdf&lt;/a&gt; version manager —using version managers is a &lt;em&gt;best practice&lt;/em&gt; in development environments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lobotuerto.com/blog/how-to-install-elixir-in-manjaro-linux/"&gt;How to install Elixir in Manjaro Linux.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Install Hex
&lt;/h2&gt;

&lt;p&gt;Let’s take on &lt;strong&gt;Hex&lt;/strong&gt; the package manager now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix local.hex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now print some info about your &lt;strong&gt;Elixir&lt;/strong&gt; stack with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix hex.info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see something along the lines of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hex: 0.17.3
Elixir: 1.6.4
OTP: 20.3.2

Built with: Elixir 1.5.3 and OTP 18.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Phoenix
&lt;/h2&gt;

&lt;p&gt;Now let’s install the framework:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install PostgreSQL
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt; is the default database for new Phoenix apps, and with good reason: It’s a solid, realiable, and well engineered relational DB.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lobotuerto.com/blog/how-to-install-postgresql-in-manjaro-linux/"&gt;How to install PostgreSQL in Manjaro Linux.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About REST clients
&lt;/h2&gt;

&lt;p&gt;You might need to get a &lt;strong&gt;REST client&lt;/strong&gt; so you can try out your &lt;strong&gt;API&lt;/strong&gt; endpoints.&lt;/p&gt;

&lt;p&gt;The two most popular ones seem to be &lt;strong&gt;Postman&lt;/strong&gt; and &lt;strong&gt;Advanced Rest Client&lt;/strong&gt; I tested both of them and I can say liked neither —at least on their Chrome app incarnations— as one didn’t display cookie info, and the other didn’t send declared variables on POST requests. ¬¬&lt;/p&gt;

&lt;p&gt;In any case if you want to try them out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can get Postman &lt;a href="https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You can get ARC &lt;a href="https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are using a web frontend library like &lt;a href="https://github.com/axios/axios"&gt;Axios&lt;/a&gt;, then your browser’s developer tools should be enough:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/devtools"&gt;Chrome DevTools.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/son/docs/Tools"&gt;Firefox Developer Tools.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you go with &lt;strong&gt;Axios&lt;/strong&gt; dont’ forget to pass the configuration option &lt;code&gt;withCredentials: true&lt;/code&gt;, this will allow the client to send cookies along when doing CORS requests.&lt;/p&gt;

&lt;p&gt;Or you can just use good ol’ &lt;code&gt;curl&lt;/code&gt; it works really well!&lt;br&gt;&lt;br&gt;
I’ll show you some examples on how to test out your endpoints from the CLI.&lt;/p&gt;


&lt;h1&gt;
  
  
  Create a new API-only Phoenix application
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Generate the app files
&lt;/h2&gt;

&lt;p&gt;In your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix phx.new my-app --app my_app --module MyApp --no-brunch --no-html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the command above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll see &lt;code&gt;my-app&lt;/code&gt; as the name for the directory created for this application.&lt;/li&gt;
&lt;li&gt;You’ll see &lt;code&gt;my_app&lt;/code&gt; used in files and directories inside &lt;code&gt;my-app/lib&lt;/code&gt; e.g. &lt;code&gt;my_app.ex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You’ll find &lt;code&gt;MyApp&lt;/code&gt; used everywhere since it’s the main module for your app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example in &lt;code&gt;my-app/lib/my_app.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  MyApp keeps the contexts that define your domain
  and business logic.

  Contexts are also responsible for managing your data, regardless
  if it comes from the database, an external API or others.
  """&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the development database
&lt;/h2&gt;

&lt;p&gt;If you created a new DB user when installing &lt;strong&gt;PostgreSQL&lt;/strong&gt; , add its credentials to&lt;code&gt;config/dev.exs&lt;/code&gt; and &lt;code&gt;config/test.exs&lt;/code&gt;. Then execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my-app
mix ecto.create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can drop the database for the &lt;em&gt;dev&lt;/em&gt; environment with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you’d like to drop the database for the &lt;em&gt;test&lt;/em&gt; environment, you’d need to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIX_ENV=test mix ecto.drop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Start the development server
&lt;/h2&gt;

&lt;p&gt;From your terminal:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Visit &lt;code&gt;http://localhost:4000&lt;/code&gt; and bask in the glory of a beautifully formatted error page. :)&lt;br&gt;&lt;br&gt;
Don’t worry though, we’ll be adding a JSON endpoint soon enough.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cCQKgSFP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lobotuerto.com/blog/building-a-json-api-with-phoenix-and-elixir/phoenix-router-error.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cCQKgSFP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lobotuerto.com/blog/building-a-json-api-with-phoenix-and-elixir/phoenix-router-error.png" alt="Router Error"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Errors in JSON for 404s and 500s
&lt;/h2&gt;

&lt;p&gt;If you don’t like to see HTML pages when there is an error and instead want to receive JSONs, set &lt;code&gt;debug_errors&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; in your &lt;code&gt;config/dev.ex&lt;/code&gt;, and restart your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:my_app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="ss"&gt;debug_errors:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, visiting &lt;code&gt;http://localhost:4000&lt;/code&gt; yields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Not Found"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  User schema (model)
&lt;/h1&gt;

&lt;p&gt;We'll be generating a new &lt;strong&gt;User&lt;/strong&gt; schema (model) inside an &lt;strong&gt;Auth&lt;/strong&gt; context.&lt;/p&gt;

&lt;p&gt;Contexts in Phoenix are cool, they serve as API boundaries that let you&lt;br&gt;
organize your application code in a better way.&lt;/p&gt;
&lt;h2&gt;
  
  
  Generate the Auth context and User schema module
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix phx.gen.context Auth User users email:string:unique password:string is_active:boolean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;From above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auth&lt;/strong&gt; is the context’s module name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User&lt;/strong&gt; is the schema’s module name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;users&lt;/strong&gt; is the DB table’s name.&lt;/li&gt;
&lt;li&gt;After that comes some field definitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The migration generated from the command above looks like this:&lt;br&gt;
&lt;/p&gt;

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

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="c1"&gt;#, null: false&lt;/span&gt;
      &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;
      &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="ss"&gt;:is_active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

      &lt;span class="n"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;unique_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust it to your liking —i.e. not allowing &lt;code&gt;null&lt;/code&gt; for emails— then run the new migration:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you want to read some info about this generator, execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix help phx.gen.context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hash a user’s password on saving
&lt;/h2&gt;

&lt;p&gt;Add a new dependency to &lt;code&gt;mix.exs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;# ...&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:bcrypt_elixir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;a href="https://github.com/riverrun/bcrypt_elixir"&gt;Bcrypt&lt;/a&gt;, we will use it to hash the user’s password before saving it; so we don’t store it as plain text inside the database.&lt;/p&gt;

&lt;p&gt;Fetch the new app dependencies with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;lib/my_app/auth/user.ex&lt;/code&gt; to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:is_active&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;validate_required&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:is_active&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;unique_constraint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hash_user_password&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;hash_user_password&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;valid?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;changes:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="no"&gt;Bcrypt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hash_pwd_salt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;hash_user_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;changeset&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the call and definitions of &lt;code&gt;hash_user_password/1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What this does is run the &lt;em&gt;changeset&lt;/em&gt; through that function, and if the changeset happens to have a &lt;code&gt;password&lt;/code&gt; key, it’ll use &lt;strong&gt;Bcrypt&lt;/strong&gt; to hash it.&lt;/p&gt;




&lt;p&gt;Running &lt;code&gt;Bcrypt.hash_pwd_salt("hola")&lt;/code&gt; would result in something like&lt;code&gt;"$2b$12$sI3PE3UsOE0BPrUv7TwUt.i4BQ32kxgK.REDv.IHC8HlEVAkqmHky"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That strange looking string is what ends up being saved in the database instead of the plain text version.&lt;/p&gt;




&lt;h3&gt;
  
  
  Fix the tests
&lt;/h3&gt;

&lt;p&gt;Run the tests for your project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now they will fail with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1) test users create_user/1 with valid data creates a user (MyApp.AuthTest)
     test/my_app/auth/auth_test.exs:32
     Assertion with == failed
     code: assert user.password() == "some password"
     left: "$2b$12$PUK73EqrvBTuOi2RiVrkOexqiVS.wIwbOtyR0EtzQLpbX6gaka8T2"
     right: "some password"
     stacktrace:
       test/my_app/auth/auth_test.exs:36: (test)

  2) test users update_user/2 with valid data updates the user (MyApp.AuthTest)
     test/my_app/auth/auth_test.exs:43
     Assertion with == failed
     code: assert user.password() == "some updated password"
     left: "$2b$12$cccPJfQD3seaBc8pHX8cJO/549lojlAjNNi/qo9QY0K7a7Zm5CaNG"
     right: "some updated password"
     stacktrace:
       test/my_app/auth/auth_test.exs:49: (test)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s because of the change we just made, the one that hashes the password.&lt;/p&gt;

&lt;p&gt;But this is easily fixed by changing those assertions to use &lt;code&gt;Bcrypt.verify_pass/2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the file &lt;code&gt;test/my_app/auth/auth_test.exs&lt;/code&gt; and change these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"create_user/1 with valid data creates a user"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"some password"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"update_user/2 with valid data updates the user"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;#...&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"some updated password"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"create_user/1 with valid data creates a user"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="no"&gt;Bcrypt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify_pass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"some password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"update_user/2 with valid data updates the user"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="no"&gt;Bcrypt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify_pass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"some updated password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;mix test&lt;/code&gt; should yield no errors.&lt;/p&gt;




&lt;h1&gt;
  
  
  Users endpoint
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generate a new JSON endpoint
&lt;/h2&gt;

&lt;p&gt;Let’s generate the users JSON endpoint, since we already have the &lt;code&gt;Auth&lt;/code&gt; context and &lt;code&gt;User&lt;/code&gt; schema available, we will pass the &lt;code&gt;--no-schema&lt;/code&gt; and &lt;code&gt;--no-context&lt;/code&gt; options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix phx.gen.json Auth User users email:string password:string is_active:boolean --no-schema --no-context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fix the tests
&lt;/h3&gt;

&lt;p&gt;Now, if you try and run your tests you’ll see this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;== Compilation error in file lib/my_app_web/controllers/user_controller.ex ==
** (CompileError) lib/my_app_web/controllers/user_controller.ex:18: undefined function user_path/3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s complaining about a missing &lt;code&gt;user_path/3&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;You need to add a &lt;code&gt;resources&lt;/code&gt; line to &lt;code&gt;lib/my_app_web/router.ex&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Declaring a resource in the router will make some helpers available for its controller —i.e. &lt;code&gt;user_path/3&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="s2"&gt;"/users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nevertheless, tests will still complain.&lt;br&gt;&lt;br&gt;
To fix them we need to make two changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comment out the &lt;code&gt;password&lt;/code&gt; line in &lt;code&gt;lib/my_app_web/views/user_view.ex&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UserView&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"user.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;user:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;# password: user.password,&lt;/span&gt;
      &lt;span class="ss"&gt;is_active:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We don’t need —nor should we— be sending the hashed password in our responses.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Since we won’t be receiving the hashed password in the response, comment out these &lt;code&gt;password&lt;/code&gt; lines in &lt;code&gt;test/my_app_web/controllers/user_controller_test.exs&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;json_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
  &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"email"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"some email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"is_active"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="c1"&gt;# "password" =&amp;gt; "some password"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;json_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
  &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"email"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"some updated email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"is_active"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
  &lt;span class="c1"&gt;# "password" =&amp;gt; "some updated password"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Tests should be fine now.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a couple of users
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Using IEx
&lt;/h3&gt;

&lt;p&gt;You can run your app inside IEx (Interactive Elixir) —this is akin to &lt;code&gt;rails console&lt;/code&gt;— with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then create a new user with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="s2"&gt;"asd@asd.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="s2"&gt;"qwerty"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using curl
&lt;/h3&gt;

&lt;p&gt;If you have &lt;code&gt;curl&lt;/code&gt; available in your terminal, you can create a new user through your endpoint using something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"user":{"email":"some@email.com","password":"some password"}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:4000/api/users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  CORS configuration
&lt;/h1&gt;

&lt;p&gt;You’ll need to configure this if you plan on having your API and frontend on different domains.&lt;br&gt;&lt;br&gt;
If you don’t know what &lt;strong&gt;CORS&lt;/strong&gt; is, have a look at this: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"&gt;Cross-Origin Resource Sharing (CORS).&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That said, here we have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/mschae/cors_plug"&gt;CorsPlug&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/whatyouhide/corsica"&gt;Corsica&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll be using &lt;strong&gt;CorsPlug&lt;/strong&gt; in this tutorial, but if you need more features for configuring your CORS requests —or want a more strict libray, try &lt;strong&gt;Corsica&lt;/strong&gt; out.&lt;/p&gt;

&lt;p&gt;Add this dependency to &lt;code&gt;mix.exs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Fetch new dependencies with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;plug CORSPlug&lt;/code&gt; to &lt;code&gt;lib/my_app_web/endpoint.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Endpoint&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;CORSPlug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;origin:&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:8080"&lt;/span&gt;

  &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Router&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can pass a list to &lt;code&gt;origin&lt;/code&gt;, as well as a regular expression, or just&lt;code&gt;plug CORSPlug&lt;/code&gt; to accept all origins —since &lt;code&gt;origin: "*"&lt;/code&gt; is the default.&lt;/p&gt;

&lt;p&gt;In my case, the rule above will accept CORS requests from a &lt;strong&gt;Vue.js&lt;/strong&gt; frontend —Vue.js development servers go up on port 8080 by default.&lt;/p&gt;




&lt;h1&gt;
  
  
  Simple authentication
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Verify a user’s password
&lt;/h2&gt;

&lt;p&gt;Let’s add some functions to the &lt;code&gt;lib/my_app/auth/auth.ex&lt;/code&gt; file to verify a user’s password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Auth&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;authenticate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;where:&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;verify_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;verify_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Wrong email or password"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;verify_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Bcrypt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify_pass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="no"&gt;false&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Wrong email or password"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  sign_in endpoint
&lt;/h2&gt;

&lt;p&gt;Then add a new &lt;code&gt;sign_in&lt;/code&gt; endpoint to &lt;code&gt;lib/my_app_web/router.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Router&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="s2"&gt;"/users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s2"&gt;"/users/sign_in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sign_in&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  sign_in controller function
&lt;/h2&gt;

&lt;p&gt;Finally add the &lt;code&gt;sign_in&lt;/code&gt; function to &lt;code&gt;lib/my_app_web/controllers/user_controller.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UserController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;sign_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"password"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authenticate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UserView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sign_in.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:unauthorized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ErrorView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"401.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define sing_in.json and 401.json views
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;lib/my_app_web/user_view.ex&lt;/code&gt; add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UserView&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"sign_in.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;user:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;data:&lt;/span&gt;
      &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;user:&lt;/span&gt;
        &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;lib/my_app_web/error_view.ex&lt;/code&gt; add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ErrorView&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"401.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;message:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;detail:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can try the &lt;code&gt;sign_in&lt;/code&gt; endpoint now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try out your new endpoint with curl
&lt;/h3&gt;

&lt;p&gt;Let’s send some POST requests to &lt;code&gt;http://localhost:4000/api/users/sign_in&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Good credentials
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"email":"asd@asd.com","password":"qwerty"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:4000/api/users/sign_in &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll receive a &lt;strong&gt;200&lt;/strong&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asd@asd.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Bad credentials
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"email":"asd@asd.com","password":"not the right password"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:4000/api/users/sign_in &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get a &lt;strong&gt;401&lt;/strong&gt; and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wrong email or password"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Sessions
&lt;/h2&gt;

&lt;p&gt;Add &lt;code&gt;plug :fetch_session&lt;/code&gt; to your &lt;code&gt;:api&lt;/code&gt; pipeline in &lt;code&gt;lib/my_app_web/router.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Save authentication status
&lt;/h3&gt;

&lt;p&gt;Now let’s modify out &lt;code&gt;sign_in&lt;/code&gt; function in &lt;code&gt;lib/my_app_web/controllers/user_controller.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UserController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;sign_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"password"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authenticate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:current_user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UserView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sign_in.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;delete_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:current_user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:unauthorized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ErrorView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"401.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Protect a resource with authentication
&lt;/h3&gt;

&lt;p&gt;Modify your &lt;code&gt;lib/my_app_web/router.ex&lt;/code&gt; to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Router&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:router&lt;/span&gt;

  &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:accepts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"json"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:fetch_session&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ss"&gt;:api_auth&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:ensure_authenticated&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s2"&gt;"/users/sign_in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sign_in&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:api_auth&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="s2"&gt;"/users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Plug function&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;ensure_authenticated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;current_user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:current_user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_user_id&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;conn&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;conn&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:unauthorized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ErrorView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"401.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message:&lt;/span&gt; &lt;span class="s2"&gt;"Unauthenticated user"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;halt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we added a new pipeline called &lt;code&gt;:api_auth&lt;/code&gt; that’ll run requests through a new &lt;code&gt;:ensure_authenticated&lt;/code&gt; plug function.&lt;/p&gt;

&lt;p&gt;We also created a new &lt;code&gt;scope "/api"&lt;/code&gt; block that pipes its requests through &lt;code&gt;:api&lt;/code&gt;then through &lt;code&gt;:api_auth&lt;/code&gt; and moved &lt;code&gt;resources "/users"&lt;/code&gt; inside.&lt;/p&gt;




&lt;p&gt;Isn’t it amazing the way you can define this stuff in Phoenix?!&lt;br&gt;&lt;br&gt;
Composability &lt;strong&gt;FTW!&lt;/strong&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Endpoint testing with curl
&lt;/h1&gt;

&lt;p&gt;Try to request a protected resource, like &lt;code&gt;/api/users&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:4000/api/users &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; cookies.txt &lt;span class="nt"&gt;-b&lt;/span&gt; cookies.txt &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unauthenticated user"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s login with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"email":"asd@asd.com","password":"qwerty"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:4000/api/users/sign_in &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; cookies.txt &lt;span class="nt"&gt;-b&lt;/span&gt; cookies.txt &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asd@asd.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, try requesting that protected resource again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:4000/api/users &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; cookies.txt &lt;span class="nt"&gt;-b&lt;/span&gt; cookies.txt &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"is_active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asd@asd.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"is_active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"some@email.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Success!&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Bonus section
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Customize your 404s and 500s JSON responses
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;lib/my_app_web/views/error_view.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ErrorView&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"404.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_assigns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;detail:&lt;/span&gt; &lt;span class="s2"&gt;"Endpoint not found!"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"500.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_assigns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;detail:&lt;/span&gt; &lt;span class="s2"&gt;"Internal server error :("&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://nithinbekal.com/posts/phoenix-authentication/"&gt;User Authentication from Scratch in Elixir and Phoenix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.walknsqualk.com/post/phoenix_fallback_controller_note/"&gt;Tip for Phoenix 1.3 Fallback Controller error&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/23039038/164276"&gt;curl: how to send cookies via command line?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.linuxask.com/questions/show-http-response-header-using-curl"&gt;Show HTTP response header using curl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This was a long one, that’s it for now folks!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>elixir</category>
      <category>phoenix</category>
      <category>api</category>
    </item>
    <item>
      <title>Quickstart guide for a new Vue.js project</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Sat, 10 Mar 2018 18:23:36 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/quickstart-guide-for-a-new-vuejs-project--5ed2</link>
      <guid>https://dev.to/lobo_tuerto/quickstart-guide-for-a-new-vuejs-project--5ed2</guid>
      <description>

&lt;p&gt;For the updated article that uses &lt;code&gt;vue-cli 3.0&lt;/code&gt; check out &lt;a href="https://lobotuerto.com/blog/quickstart-guide-for-a-new-vuejs-project/"&gt;Quickstart guide for a new Vue.js project with vue-cli 3.0.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also includes a content table for easy navigation over there. ;)&lt;/p&gt;




&lt;h1&gt;
  
  
  Opinions
&lt;/h1&gt;

&lt;p&gt;In the little time I have delving into &lt;a href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt; I’ve come to really appreciate the framework, and its surrounding libraries.&lt;/p&gt;

&lt;p&gt;This &lt;em&gt;opinionated&lt;/em&gt; guide details the steps I take to start with a solid foundation for a new &lt;strong&gt;Vue.js&lt;/strong&gt; project.&lt;/p&gt;




&lt;p&gt;What particular opinions does it include?&lt;br&gt;&lt;br&gt;
Well, for starters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Package manager:&lt;/strong&gt; &lt;a href="https://yarnpkg.com/en/"&gt;Yarn&lt;/a&gt; — Fast, reliable, and secure dependency management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project generation tool:&lt;/strong&gt; &lt;a href="https://github.com/vuejs/vue-cli/tree/v2.9.3"&gt;vue-cli&lt;/a&gt; — CLI for rapid Vue.js development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI framework:&lt;/strong&gt; &lt;a href="https://vuetifyjs.com/"&gt;Vuetify&lt;/a&gt; — Material Design component framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Material icons library:&lt;/strong&gt; &lt;a href="https://material.io/icons/"&gt;Google Material Icons&lt;/a&gt; — Beautifully crafted, delightful, and easy to use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation library:&lt;/strong&gt; &lt;a href="https://monterail.github.io/vuelidate/"&gt;Vuelidate&lt;/a&gt; — Simple, lightweight model-based validation for Vue.js.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ajax library:&lt;/strong&gt; &lt;a href="https://github.com/axios/axios"&gt;Axios&lt;/a&gt; — Promise based HTTP client for the browser and Node.js.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have found that these tools and libraries are performant, intuitive and very easy to work with.&lt;/p&gt;



&lt;p&gt;I had a similar stack for &lt;a href="https://angular.io/"&gt;Angular&lt;/a&gt; that included &lt;a href="https://material.angular.io/"&gt;Angular Material&lt;/a&gt; plus some custom component primitives for rendering dynamic forms, data tables and other stuff.&lt;/p&gt;

&lt;p&gt;I was really fond of the dynamic forms implementation, it allowed the user to specify &lt;em&gt;highly configurable&lt;/em&gt; forms using a simple JSON specification.&lt;br&gt;&lt;br&gt;
The generated forms integrated well with our &lt;a href="http://rubyonrails.org/"&gt;Rails&lt;/a&gt; &lt;a href="http://jsonapi.org/"&gt;JSON API&lt;/a&gt; backend.&lt;/p&gt;

&lt;p&gt;I plan to write a tutorial about doing the same thing but this time with &lt;strong&gt;Vue.js&lt;/strong&gt; and &lt;strong&gt;Vuetify&lt;/strong&gt; , but I digress…&lt;/p&gt;
&lt;h1&gt;
  
  
  Setting up a new Vue.js app for success
&lt;/h1&gt;

&lt;p&gt;Here we’ll see how to setup a newly created app with &lt;strong&gt;vue-cli&lt;/strong&gt; so it’ll be ready for us to start hacking on it right away.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Install Node.js, Yarn and vue-cli
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lobotuerto.com/blog/como-instalar-nodejs-en-ubuntu/"&gt;How to install Node.js in Ubuntu.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lobotuerto.com/blog/how-to-install-nodejs-in-manjaro-linux/"&gt;How to install Node.js in Manjaro Linux.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Generate a new project
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vue init webpack my-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I usually accept all defaults, except for the package manager.&lt;br&gt;&lt;br&gt;
I pick &lt;strong&gt;Yarn&lt;/strong&gt; when asked.&lt;/p&gt;

&lt;p&gt;As you can see we are using the &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt; template.&lt;br&gt;&lt;br&gt;
Here is the list for the &lt;a href="https://github.com/vuejs/vue-cli/tree/v2.9.3#official-templates"&gt;official templates.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Adjust ESLint rules
&lt;/h2&gt;

&lt;p&gt;Add this line to the &lt;code&gt;rules&lt;/code&gt; key in the &lt;code&gt;.eslintrc.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-multiple-empty-lines&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason for this change, is that I usually leave two consecutive blank lines between some elements inside my &lt;strong&gt;.vue&lt;/strong&gt; component files.&lt;/p&gt;

&lt;p&gt;For example between &lt;code&gt;import&lt;/code&gt; sections and following code.&lt;br&gt;&lt;br&gt;
Or between &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install project dependencies
&lt;/h2&gt;

&lt;p&gt;Use &lt;strong&gt;Yarn&lt;/strong&gt; to add the project dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add vuetify material-design-icons vuelidate axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like having the power of &lt;strong&gt;SCSS / SASS&lt;/strong&gt; at my disposal when writing &lt;strong&gt;CSS&lt;/strong&gt; rules.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--dev&lt;/code&gt; will add dependencies to the &lt;code&gt;devDependencies&lt;/code&gt; section in your&lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add sass-loader node-sass &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initial app configuration and setup
&lt;/h2&gt;

&lt;p&gt;To setup &lt;strong&gt;Vuetify&lt;/strong&gt; , &lt;strong&gt;Google Material Icons&lt;/strong&gt; and &lt;strong&gt;Vuelidate&lt;/strong&gt; , you need to add these lines to &lt;code&gt;src/main.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vuelidate&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vuelidate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vuetify&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vuetify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;material-design-icons/iconfont/material-icons.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vuetify/dist/vuetify.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Vuelidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Vuetify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see &lt;strong&gt;Vuetify&lt;/strong&gt; in action, change your &lt;code&gt;src/App.vue&lt;/code&gt; file to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;v-app&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;router-view/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/v-app&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And your &lt;code&gt;src/components/HelloWorld.vue&lt;/code&gt; to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;v-content&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;v-btn&amp;gt;&lt;/span&gt;
      Hello!
    &lt;span class="nt"&gt;&amp;lt;/v-btn&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/v-content&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HelloWorld&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Typography
&lt;/h2&gt;

&lt;p&gt;The Material Design &lt;a href="https://material.io/guidelines/style/typography.html"&gt;guidelines for typography,&lt;/a&gt; state that &lt;strong&gt;Roboto&lt;/strong&gt; —and &lt;strong&gt;Noto&lt;/strong&gt; — are the standard typefaces to use.&lt;/p&gt;

&lt;p&gt;Add this to the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of your &lt;code&gt;index.html&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Have a look
&lt;/h2&gt;

&lt;p&gt;Start your project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And visit: &lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That’s it!&lt;br&gt;&lt;br&gt;
Have a good one. :)&lt;/p&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.monterail.com/blog/2016/rethinking-validations-for-vue-js"&gt;Rethinking validations for Vue.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>vuetify</category>
    </item>
    <item>
      <title>How to install Node.js in Manjaro Linux</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Sat, 10 Mar 2018 16:23:36 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/how-to-install-nodejs-in-manjaro-linux--5ha4</link>
      <guid>https://dev.to/lobo_tuerto/how-to-install-nodejs-in-manjaro-linux--5ha4</guid>
      <description>

&lt;p&gt;You can check the latest updated version of this article at &lt;a href="https://lobotuerto.com/blog/how-to-install-nodejs-in-manjaro-linux/"&gt;lobotuerto's notes - How to install Node.js in Manjaro Linux.&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Installation process
&lt;/h1&gt;

&lt;p&gt;Version managers rule in dev environments.&lt;br&gt;&lt;br&gt;
So we will install &lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt; through &lt;a href="https://github.com/creationix/nvm"&gt;nvm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Install the &lt;code&gt;nvm&lt;/code&gt; package from the &lt;a href="https://wiki.archlinux.org/index.php/Arch_User_Repository"&gt;AUR&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pacaur -S nvm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then on your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'source /usr/share/nvm/init-nvm.sh' &amp;gt;&amp;gt; ~/.bashrc
exec $SHELL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To list all available versions for &lt;strong&gt;Node.js&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvm ls-remote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s install latest from the &lt;strong&gt;9&lt;/strong&gt; series:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvm install 9
node -v #v9.8.0
npm -v #5.6.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the &lt;a href="https://yarnpkg.com/en/"&gt;Yarn&lt;/a&gt; package manager globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to add &lt;strong&gt;Yarn’s&lt;/strong&gt; binary to our &lt;code&gt;$PATH&lt;/code&gt; in &lt;code&gt;~/.bashrc&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
In a terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'export PATH=$PATH:~/.yarn/bin' &amp;gt;&amp;gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are a &lt;a href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt; fan —and why shouldn’t you be one? :)— install &lt;a href="https://github.com/vuejs/vue-cli"&gt;vue-cli&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn global add vue-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/index.php/Node.js"&gt;Node.js in the ArchWiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>linux</category>
      <category>node</category>
      <category>manjaro</category>
    </item>
    <item>
      <title>Fluid SVGs with Vue.js</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Fri, 09 Mar 2018 15:09:09 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/fluid-svgs-with-vuejs--3eah</link>
      <guid>https://dev.to/lobo_tuerto/fluid-svgs-with-vuejs--3eah</guid>
      <description>&lt;p&gt;I really like going for fluid SVGs when doing data visualization.&lt;/p&gt;

&lt;p&gt;Fluid SVGs are the ones that can extend on the horizontal axis as far as the &lt;em&gt;parent&lt;/em&gt; allows it. They preserve their aspect ratio, growing and shrinking accordingly to adjust themselves if their size ever changes.&lt;/p&gt;

&lt;p&gt;The trick lies in how you define the &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; element, specially its &lt;code&gt;viewBox&lt;/code&gt; attribute.&lt;br&gt;&lt;br&gt;
Also, don’t define a &lt;code&gt;height&lt;/code&gt; or &lt;code&gt;width&lt;/code&gt; on it.&lt;/p&gt;



&lt;p&gt;Here is a single file component in &lt;strong&gt;Vue.js&lt;/strong&gt; that will behave exactly like that.&lt;br&gt;&lt;br&gt;
Let’s name it &lt;code&gt;src/components/FluidSvg.vue&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;:viewBox=&lt;/span&gt;&lt;span class="s"&gt;"viewBoxString"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"my-square"&lt;/span&gt;
        &lt;span class="na"&gt;:x=&lt;/span&gt;&lt;span class="s"&gt;"rect.x"&lt;/span&gt;
        &lt;span class="na"&gt;:y=&lt;/span&gt;&lt;span class="s"&gt;"rect.y"&lt;/span&gt;
        &lt;span class="na"&gt;:width=&lt;/span&gt;&lt;span class="s"&gt;"rect.width"&lt;/span&gt;
        &lt;span class="na"&gt;:height=&lt;/span&gt;&lt;span class="s"&gt;"rect.height"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FluidSvg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;viewBoxString&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`0 0 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;antiquewhite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.my-square&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, use it inside some other component like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"example-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;fluid-svg&amp;gt;&amp;lt;/fluid-svg&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"example-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;fluid-svg&amp;gt;&amp;lt;/fluid-svg&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"example-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;fluid-svg&amp;gt;&amp;lt;/fluid-svg&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;FluidSvg&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/FluidSvg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HelloWorld&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FluidSvg&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.example-1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.example-2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.example-3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what you’ll see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HHXN9RD0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lobotuerto.com/blog/fluid-svgs-with-vuejs/fluid-svgs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HHXN9RD0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lobotuerto.com/blog/fluid-svgs-with-vuejs/fluid-svgs.png" alt="Fluid SVGs"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>svg</category>
    </item>
    <item>
      <title>How to install Elixir in Manjaro Linux</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Thu, 08 Mar 2018 14:20:48 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/how-to-install-elixir-in-manjaro-linux--3mo8</link>
      <guid>https://dev.to/lobo_tuerto/how-to-install-elixir-in-manjaro-linux--3mo8</guid>
      <description>

&lt;p&gt;You can check the latest updated version of this article at &lt;a href="https://lobotuerto.com/blog/how-to-install-elixir-in-manjaro-linux/"&gt;lobotuerto's notes - How to install Elixir in Manjaro Linux.&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Installation process
&lt;/h1&gt;

&lt;p&gt;I really like version managers for my dev languages.&lt;/p&gt;

&lt;p&gt;I’ve been using &lt;a href="https://github.com/asdf-vm/asdf"&gt;asdf&lt;/a&gt; for installing &lt;a href="https://www.erlang.org/"&gt;Erlang&lt;/a&gt; and &lt;a href="https://elixir-lang.org/"&gt;Elixir&lt;/a&gt; with &lt;strong&gt;OTP&lt;/strong&gt; support.&lt;/p&gt;

&lt;p&gt;Let’s start!&lt;/p&gt;

&lt;p&gt;Clone the &lt;strong&gt;GitHub&lt;/strong&gt; repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.4.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add some lines to your &lt;code&gt;.bashrc&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e '\n. $HOME/.asdf/asdf.sh' &amp;gt;&amp;gt; ~/.bashrc
echo -e '\n. $HOME/.asdf/completions/asdf.bash' &amp;gt;&amp;gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make changes to &lt;code&gt;.bashrc&lt;/code&gt; effective or just close and open your terminal:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Finally install &lt;strong&gt;Erlang&lt;/strong&gt; and &lt;strong&gt;Elixir:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf plugin-add erlang
asdf list-all erlang
asdf install erlang 20.2.4
asdf global erlang 20.2.4

asdf plugin-add elixir
asdf list-all elixir
asdf install elixir 1.6.2-otp-20
asdf global elixir 1.6.2-otp-20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To activate &lt;code&gt;iex&lt;/code&gt; REPL history, add this to your &lt;code&gt;.bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export ERL_AFLAGS="-kernel shell_history enabled"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using this &lt;a href="https://code.visualstudio.com/"&gt;awesome editor&lt;/a&gt; (hint: &lt;strong&gt;Visual Studio Code&lt;/strong&gt; ), you should try the &lt;a href="https://github.com/JakeBecker/vscode-elixir-ls"&gt;ElixirLS&lt;/a&gt; extension.&lt;/p&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elixirschool.com/en/"&gt;Elixir School — Lessons about the Elixir programming language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ropig.com/blog/ten-things-wish-knew-using-elixir/"&gt;Ten things I wish I knew before using Elixir&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>linux</category>
      <category>elixir</category>
      <category>manjaro</category>
    </item>
    <item>
      <title>How to install PostgreSQL in Manjaro Linux</title>
      <dc:creator>Víctor Adrián</dc:creator>
      <pubDate>Thu, 08 Mar 2018 13:46:45 +0000</pubDate>
      <link>https://dev.to/lobo_tuerto/how-to-install-postgresql-in-manjaro-linux--24bj</link>
      <guid>https://dev.to/lobo_tuerto/how-to-install-postgresql-in-manjaro-linux--24bj</guid>
      <description>&lt;h1&gt;
  
  
  Installation process
&lt;/h1&gt;

&lt;p&gt;Setting up &lt;strong&gt;PostgreSQL&lt;/strong&gt; in &lt;strong&gt;Manjaro Linux&lt;/strong&gt; is very easy.&lt;/p&gt;

&lt;p&gt;Just follow these steps and you’ll have a working installation in no time.&lt;/p&gt;

&lt;p&gt;Install the &lt;code&gt;postgresql&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo pacman -S postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then setup a password for the &lt;code&gt;postgres&lt;/code&gt; user with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo passwd postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switch to the &lt;code&gt;postgres&lt;/code&gt; user account and initialize the database cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su postgres -l # or sudo -u postgres -i
initdb --locale $LANG -E UTF8 -D '/var/lib/postgres/data/'
exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Options for &lt;code&gt;initdb&lt;/code&gt; are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--locale&lt;/code&gt; is the one defined in &lt;code&gt;/etc/locale.conf&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-E&lt;/code&gt; is the default encoding for new databases.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-D&lt;/code&gt; is the default location for storing the database cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, start and enable the &lt;code&gt;postgresql.service&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl enable --now postgresql.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it!&lt;/p&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/index.php/PostgreSQL"&gt;PostgreSQL in the ArchWiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/index.php/Systemd"&gt;systemd in the ArchWiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>linux</category>
      <category>postgres</category>
      <category>manjaro</category>
    </item>
  </channel>
</rss>
