<?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: Mark</title>
    <description>The latest articles on DEV Community by Mark (@logicmason).</description>
    <link>https://dev.to/logicmason</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%2F158342%2Fa81fa956-ee17-4eb6-a106-15196e0c296d.jpg</url>
      <title>DEV Community: Mark</title>
      <link>https://dev.to/logicmason</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/logicmason"/>
    <language>en</language>
    <item>
      <title>The .iex.exs file</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Thu, 06 Feb 2020 08:03:11 +0000</pubDate>
      <link>https://dev.to/logicmason/the-iex-exs-file-236i</link>
      <guid>https://dev.to/logicmason/the-iex-exs-file-236i</guid>
      <description>&lt;p&gt;The &lt;code&gt;.iex.exs&lt;/code&gt; file is a "must have" convenience.&lt;/p&gt;

&lt;p&gt;You can use it to set aliases, set imports and add define helper functions for every IEx session you run!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/E0bmtcYrz9M"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here's what's in my global one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;import_if_available&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;Query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;import_if_available&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="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;AC&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;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;changes&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;schema&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;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="o"&gt;.&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;changes&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;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="no"&gt;IEx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="ss"&gt;colors:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="ss"&gt;syntax_colors:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="ss"&gt;number:&lt;/span&gt; &lt;span class="ss"&gt;:light_yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;atom:&lt;/span&gt; &lt;span class="ss"&gt;:light_cyan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;string:&lt;/span&gt; &lt;span class="ss"&gt;:light_black&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;:light_blue&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="ss"&gt;nil:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:magenta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bright&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;ls_directory:&lt;/span&gt; &lt;span class="ss"&gt;:cyan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;ls_device:&lt;/span&gt; &lt;span class="ss"&gt;:yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;doc_code:&lt;/span&gt; &lt;span class="ss"&gt;:green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;doc_inline_code:&lt;/span&gt; &lt;span class="ss"&gt;:magenta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;doc_headings:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:cyan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:underline&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;doc_title:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:cyan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bright&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:underline&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;default_prompt:&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;# ANSI CHA, move cursor to column 1&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[G"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;:light_magenta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;# plain string&lt;/span&gt;
        &lt;span class="s2"&gt;"🧪 iex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;:white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;:reset&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;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ANSI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&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;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chardata_to_string&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;And in this project, my local &lt;code&gt;.iex.exs&lt;/code&gt; has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Campsite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Accounts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Accounts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Credential&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Comment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Episode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Podcast&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Game&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With these in place, every time IEx starts up, commonly used modules are automatically aliased, Ecto queries are easier and there's a nice 🧪 prompt making it clear the terminal is in IEx. 🎉&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Request a free email-based Elixir course from &lt;a href="https://alchemist967856.typeform.com/to/FA0SUF"&gt;Alchemist.Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>setup</category>
      <category>iex</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Querying nested JSONB fields with Ecto</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Mon, 30 Dec 2019 10:37:54 +0000</pubDate>
      <link>https://dev.to/logicmason/querying-nested-jsonb-fields-with-ecto-4372</link>
      <guid>https://dev.to/logicmason/querying-nested-jsonb-fields-with-ecto-4372</guid>
      <description>&lt;p&gt;Ecto has a map type, which is implemented in Postgres as a JSONB field. It's particularly useful for situations involving user-submitted data, where we don't know the exact shape the data will come in.&lt;/p&gt;

&lt;p&gt;Consider this schema for user-submitted reviews:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;CreateReview&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;:reviews&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;:submitter_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;references&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="n"&gt;add&lt;/span&gt; &lt;span class="ss"&gt;:item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="ss"&gt;:rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="mi"&gt;0&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;add&lt;/span&gt; &lt;span class="ss"&gt;:metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:map&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;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:submitter_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:item_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&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;:reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:submitter_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:item_id&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

    &lt;span class="c1"&gt;# How do we create an index a JSONB sub-field?&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;
  
  
  Querying into JSONB fields with raw SQL
&lt;/h3&gt;

&lt;p&gt;Over time, we might come to find that some reviews include an &lt;code&gt;item&lt;/code&gt; field in their metadata. These can be queried in the DB with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'item'&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Digging in further we could examine only reviews with an an item field in the metadata and &lt;em&gt;another&lt;/em&gt; nested field price. To find all reviews with such a structure and a price of 35, we can do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;@&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'{"item": {"price": 35}}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'item'&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'35'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note: The difference between &lt;code&gt;-&amp;gt;&lt;/code&gt; and &lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt; is that &lt;code&gt;-&amp;gt;&lt;/code&gt; returns a JSON object and &lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt; returns the value as text!&lt;/p&gt;

&lt;h3&gt;
  
  
  Ecto Fragments
&lt;/h3&gt;

&lt;p&gt;Ecto provides a handy escape hatch to use SQL for more specialized queries such as these. Assuming &lt;code&gt;Ecto.Query&lt;/code&gt; has been imported, you can wrap the SQL you need in a &lt;code&gt;fragment&lt;/code&gt; call.  The following returns all the items within review metadata fields that have a price:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"reviews"&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;fragment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"metadata-&amp;gt;'item'-&amp;gt;'price' is not null"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;select:&lt;/span&gt; &lt;span class="n"&gt;fragment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"metadata-&amp;gt;'item'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note: When using the &lt;code&gt;@&amp;gt;&lt;/code&gt; JSON syntax, it's often convenient to use the &lt;code&gt;~s&lt;/code&gt; sigil with either &lt;code&gt;|&lt;/code&gt; as delimiters and avoid a lot of backslash escaping. For example, using the JSON syntax to get a count of items with price 35 like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&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="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"events"&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;fragment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;~s|metadata @&amp;gt; '{"item":{"price": 35}}'|&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;select:&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating indexes on JSONB sub fields
&lt;/h3&gt;

&lt;p&gt;In a large table where a particularly embedded field is important enough to query, such as &lt;code&gt;price&lt;/code&gt; in this case, it's a good idea to add an index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'item'&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Inside Ecto migrations, we can accomplish this by wrapping the command in an &lt;code&gt;execute()&lt;/code&gt;. Returning to the question at the top of this page, we can simply add the execute to the bottom of the change function in our migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:submitter_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:item_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&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;:reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:submitter_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:item_id&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="c1"&gt;# How do we create an index on a JSONB sub-field?&lt;/span&gt;
&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"CREATE INDEX ON reviews((metadata-&amp;gt;'item'-&amp;gt;&amp;gt;'price'));"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Request a free email-based Elixir course from &lt;a href="https://alchemist967856.typeform.com/to/FA0SUF"&gt;Alchemist.Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>json</category>
      <category>ecto</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Elixir Structs are maps with checks and default values</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Sat, 28 Dec 2019 11:10:10 +0000</pubDate>
      <link>https://dev.to/logicmason/elixir-structs-are-maps-with-checks-and-default-values-135m</link>
      <guid>https://dev.to/logicmason/elixir-structs-are-maps-with-checks-and-default-values-135m</guid>
      <description>&lt;p&gt;After our crash course, &lt;a href="https://alchemist.camp/articles/how-to-update-elixir-maps"&gt;Elixir maps made effortless&lt;/a&gt;, the next logical building block is structs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Elixir Structs?
&lt;/h2&gt;

&lt;p&gt;As explained in the official docs, &lt;em&gt;Structs are extensions built on top of maps that provide compile-time checks and default values&lt;/em&gt;. Maps, as we covered, are one of Elixir's basic data structures. They're the primary way we store key-value pairs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
  &lt;span class="s2"&gt;"sam"&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;age:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"pat"&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;age:&lt;/span&gt; &lt;span class="mi"&gt;58&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;gt;&lt;/span&gt; &lt;span class="n"&gt;user1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sam"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;22&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;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;

&lt;span class="c1"&gt;# Or in one step...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"pat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="mi"&gt;58&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Aside from getting values from maps via standard library functions like &lt;code&gt;Map.get/3&lt;/code&gt; or &lt;code&gt;Kernel.get_in/2&lt;/code&gt;, there are also two built-in syntaxes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The dot syntax, which throws errors on missing keys
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ss"&gt;:weight&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The [] syntax, which is forgiving:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:nobody&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="no"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that the dot syntax assumes keys are atoms and if keys are Strings as above, only the bracket syntax can be used. For more on working with maps, see: &lt;a href="https://alchemist.camp/articles/how-to-update-elixir-maps"&gt;Elixir maps made effortless&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Structs are built on top of maps
&lt;/h2&gt;

&lt;p&gt;Let's try pasting a simple module with a &lt;code&gt;defstruct&lt;/code&gt; into iex and then poking around at it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="ss"&gt;:nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"anonymous"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&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;age:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;%&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;age:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"anonymous"&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;user2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;%&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;age:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"anonymous"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using a struct makes it possible to define default values. It also lets us be confident that any &lt;code&gt;User&lt;/code&gt; we create will at least have the two keys of &lt;code&gt;age&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt;. It also makes it possible for us to match various kinds of structs in a case statement, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;user1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;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="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="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This is a user"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Admin&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;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This is an admin"&lt;/span&gt;&lt;span class="p"&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="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I don't know what this is"&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 will do a &lt;strong&gt;compile-time&lt;/strong&gt; check to ensure both the structs are defined and then it will check the hidden &lt;code&gt;__struct__&lt;/code&gt; key of &lt;code&gt;user1&lt;/code&gt; to see which kind of struct it is. If the &lt;code&gt;Admin&lt;/code&gt; struct isn't defined, then you'll see this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__struct__&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="n"&gt;expand&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt; &lt;span class="no"&gt;Admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Enforcing keys
&lt;/h2&gt;

&lt;p&gt;We can go a step further. By using &lt;code&gt;@enforce_keys&lt;/code&gt; at the top of a struct module, we can enforce that a specific set of keys are used when creating a struct&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@enforce_keys&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="ss"&gt;:nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"anonymous"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;favorite_color:&lt;/span&gt; &lt;span class="s2"&gt;"purple"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, we'll see the following in iex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&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;the&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;also&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;given&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;building&lt;/span&gt; &lt;span class="n"&gt;struct&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;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&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;name:&lt;/span&gt; &lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;favorite_food:&lt;/span&gt; &lt;span class="s2"&gt;"steak"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ss"&gt;:favorite_food&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&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;name:&lt;/span&gt; &lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="s2"&gt;"48"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;%&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;age:&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;favorite_color:&lt;/span&gt; &lt;span class="s2"&gt;"purple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, users &lt;strong&gt;must&lt;/strong&gt; have names and ages, but favorite colors are optional. Any other key is invalid. Again, this is enforced at compile-time, so it is possible to patch together a struct that violates the specified behavior by directly setting the &lt;code&gt;__struct__&lt;/code&gt; field rather than using the &lt;code&gt;%User{}&lt;/code&gt; syntax. This isn't a good idea to abuse, but it can be useful in some situations when building libraries.&lt;/p&gt;

&lt;p&gt;Here's how we could create a "user" who's missing a required key &lt;em&gt;and&lt;/em&gt; includes a key that isn't part of the %User{} struct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;evil_bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;__struct__:&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;name:&lt;/span&gt; &lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;favorite_food:&lt;/span&gt; &lt;span class="s2"&gt;"steak"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;evil_bob&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&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="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="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This is a 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;_&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="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This isn't a 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="k"&gt;end&lt;/span&gt;
&lt;span class="no"&gt;This&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="ss"&gt;:ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



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

&lt;h2&gt;
  
  
  A hands-on example
&lt;/h2&gt;

&lt;p&gt;If you want to dig into a simple, plain Elixir project using Structs, take a look at the &lt;a href="https://alchemist.camp/episodes/tictac-game-board"&gt;Tic-tac-toe game board&lt;/a&gt; screencast!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Request a free email-based Elixir course from &lt;a href="https://alchemist967856.typeform.com/to/FA0SUF"&gt;Alchemist.Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>basics</category>
      <category>maps</category>
      <category>structs</category>
    </item>
    <item>
      <title>Setting up PrismJS with Phoenix</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Mon, 16 Dec 2019 09:47:02 +0000</pubDate>
      <link>https://dev.to/logicmason/setting-up-prismjs-with-phoenix-384</link>
      <guid>https://dev.to/logicmason/setting-up-prismjs-with-phoenix-384</guid>
      <description>&lt;p&gt;PrismJS is a great option for code syntax highlighting. It's used by Stripe, along with many other companies that deeply value documentation.&lt;/p&gt;

&lt;p&gt;It supports a vast array of plugins and the total script weighs in at just 2k, gziped. Extra programming languages add 0.3-0.5KB each and themes are around 1KB. All in all, it's a lot of functionality for very little cost to your page load times!&lt;/p&gt;

&lt;p&gt;This is a quick guide to get it set up on Phoenix (or just about any back-end framework that takes an agnostic approach towards JS). The code shown &lt;em&gt;in this post&lt;/em&gt;, as well as on Alchemist Camp uses this setup.&lt;/p&gt;

&lt;p&gt;This guide starts from a fresh Phoenix app. It &lt;em&gt;should&lt;/em&gt; work with just about any standard app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Prism
&lt;/h2&gt;

&lt;p&gt;First, &lt;code&gt;cd&lt;/code&gt; into your &lt;code&gt;assets&lt;/code&gt; directory and then install the following two libraries. If you're using yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add prismjs
yarn add babel-plugin-prismjs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or, if you're using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;prismjs
npm &lt;span class="nb"&gt;install &lt;/span&gt;babel-plugin-prismjs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, to include it in your front-end, add the following to the top of your main &lt;code&gt;app.js&lt;/code&gt; file:&lt;br&gt;
&lt;code&gt;import Prism from "prismjs"&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding support for more languages
&lt;/h3&gt;

&lt;p&gt;Prism supports syntax highlighting for well over a hundred languages, but it doesn't load them all by default. We can configure which languages load and pick a theme by creating a &lt;code&gt;.babelrc&lt;/code&gt; file in our assets directory. Here's an example file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;presets&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;plugins&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="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prismjs&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;languages&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;elixir&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;erlang&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markdown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ruby&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="c1"&gt;// themes can be found in this directory:&lt;/span&gt;
        &lt;span class="c1"&gt;// assets/node_modules/prismjs/themes&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;okaidia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Customizing the theme
&lt;/h3&gt;

&lt;p&gt;I wanted the styling from the okaidia theme for blocks of pre-formated code, but wanted my own styles to control inline code. So I commented out the theme line above, copied the theme file from its directory into the &lt;code&gt;/assets/css&lt;/code&gt; directory where Phoenix puts stylesheets. Then removed the styles I didn't want and re-wrote it to match my specific needs. All the Prism themes are is CSS, so you can adjust them without concern about breaking anything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Prism works
&lt;/h3&gt;

&lt;p&gt;Prism will add syntax highlighting to inline &lt;code&gt;code&lt;/code&gt; tags and to &lt;code&gt;pre&lt;/code&gt; blocks with &lt;code&gt;code&lt;/code&gt; inside them. The language of highlighting applied is determined by the class of the element. If the class is &lt;code&gt;language-javascript&lt;/code&gt;, the highlighting will be for JavaScript, a class of &lt;code&gt;language-elixir&lt;/code&gt; will apply Elixir highlighting, and so on. For the full list, refer to &lt;a href="https://prismjs.com/#supported-languages"&gt;Prism's supported language chart&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also set a default language by setting a class on a parent element, such as the &lt;code&gt;body&lt;/code&gt; tag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add code to a page
&lt;/h3&gt;

&lt;p&gt;Phoenix apps come with an &lt;code&gt;index.html.eex&lt;/code&gt; template for the &lt;code&gt;/&lt;/code&gt; page. Try replacing yours to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;code = &lt;/span&gt;&lt;span class="s"&gt;~s"""&lt;/span&gt;
  &lt;span class="na"&gt;defmodule&lt;/span&gt; &lt;span class="na"&gt;MyModule&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt;
    &lt;span class="na"&gt;#stuff&lt;/span&gt;
  &lt;span class="na"&gt;end&lt;/span&gt;
  &lt;span class="err"&gt;"""%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;code&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"language-elixir"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Enum.at([:a, :b, :c], 1) |&amp;gt; IO.puts()&lt;span class="nt"&gt;&amp;lt;/code&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"language-elixir"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(The top line is just saving our block of code in a variable &lt;code&gt;code&lt;/code&gt;, using a HEREDOC string so we don't have to worry about new lines or indentation inside the &lt;code&gt;pre&lt;/code&gt; block!)&lt;/p&gt;

&lt;p&gt;Here's the result:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NdkWf4ZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dropbox.com/s/ar94ezeotyvbfyj/AC%2520syntax%2520highlighting%25206.png%3Fraw%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NdkWf4ZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dropbox.com/s/ar94ezeotyvbfyj/AC%2520syntax%2520highlighting%25206.png%3Fraw%3D1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Integrating with Earmark
&lt;/h3&gt;

&lt;p&gt;If you're using &lt;a href="https://github.com/pragdave/earmark"&gt;Earmark&lt;/a&gt; to convert Markdown to HTML (&lt;a href="https://alchemist.camp/tagged/Markdown"&gt;as this site does&lt;/a&gt;), then you'll need to pass in a &lt;code&gt;code_class_prefix&lt;/code&gt; option to generate the appropriate classes on your code blocks. E.g:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="no"&gt;Earmark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_html!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Earmark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;code_class_prefix:&lt;/span&gt; &lt;span class="s2"&gt;"lang-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;smartypants:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then you can declare the language of your code blocks in Markdown like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-markdown"&gt;

```ruby
  puts 8 ** 3
```


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




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://alchemist.camp"&gt;Alchemist Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>phoenix</category>
      <category>prismjs</category>
      <category>earmark</category>
    </item>
    <item>
      <title>Running a Gatsby blog inside a Phoenix app</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Mon, 07 Oct 2019 02:35:15 +0000</pubDate>
      <link>https://dev.to/logicmason/running-a-gatsby-blog-inside-a-phoenix-app-c5l</link>
      <guid>https://dev.to/logicmason/running-a-gatsby-blog-inside-a-phoenix-app-c5l</guid>
      <description>&lt;p&gt;Let's see what it takes to set up a Gatsby blog inside a Phoenix app!&lt;/p&gt;

&lt;p&gt;Like Jekyll, VuePress and other popular static site generators, Gatsby is a easy way to create a snappy blog. Since it generates plain HTML, CSS and JS (aka "a static site"), all that's really needed is to drop the files in a directory that serves static contents.&lt;/p&gt;

&lt;p&gt;By default, Phoenix includes a directory for serving static assets at &lt;code&gt;/assets/static&lt;/code&gt;. Any files and subdirectories named in the &lt;code&gt;only:&lt;/code&gt; key of &lt;code&gt;Plug.Static&lt;/code&gt; inside your &lt;code&gt;endpoint.ex&lt;/code&gt; file will be loaded from this static assets directory instead of being delegated to your router.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you've &lt;a href="https://alchemist.camp/episodes/asdf-language-versions"&gt;installed Node, Elixir and Phoenix&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install the Gatsby CLI: &lt;code&gt;npm install -g gatsby-cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a new Phoenix app: &lt;code&gt;mix phx.new my_app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go into the newly created directory: &lt;code&gt;cd my_app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Generate the DB: &lt;code&gt;mix ecto.setup&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go into the assets directory (of your new app): &lt;code&gt;cd assets&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a Gatsby site inside &lt;code&gt;assets&lt;/code&gt;: &lt;code&gt;gatsby new gatsby https://github.com/gatsbyjs/gatsby-starter-hello-world&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Verify the installations were successful
&lt;/h2&gt;

&lt;p&gt;At this point, you should be able to start your Phoenix app by running &lt;code&gt;mix phx.server&lt;/code&gt; from the base of your project, the &lt;code&gt;my_app&lt;/code&gt; directory and opening &lt;code&gt;localhost:4000&lt;/code&gt; in your web browser.&lt;/p&gt;

&lt;p&gt;The static site generated by Gatsby can be run in development mode by running &lt;code&gt;gatsby develop&lt;/code&gt; from &lt;code&gt;my_app/assets/gatsby&lt;/code&gt; and then opening &lt;code&gt;localhost:8000&lt;/code&gt;. It's just a "Hello world!" for now.&lt;/p&gt;

&lt;p&gt;We named the site "gatsby" in the previous section so that it's clear, from the context of the enclosing Phoenix project, that this is a Gatsby site. &lt;/p&gt;

&lt;h2&gt;
  
  
  Generate the static site
&lt;/h2&gt;

&lt;p&gt;In order to run the static site in production, we'll want to build a production bundle. The command to do it is &lt;code&gt;gatsby build&lt;/code&gt;. By default this will build the site under a directory called "public", which in our case will be at &lt;code&gt;my_app/assets/gatsby/public&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This isn't ideal.&lt;/p&gt;

&lt;p&gt;We need to serve the output of the Gatsby build from our Phoenix static assets directory, but don't want to serve our Gatsby project's &lt;code&gt;src&lt;/code&gt; or other directories publicly. There is an &lt;code&gt;--output-dir&lt;/code&gt; flag that can be passed to the &lt;code&gt;gatsby build&lt;/code&gt; command, but at the time of this writing, it's not possible to pass an output directory outside the Gatsby project, only the name of the directory is configurable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a symlink
&lt;/h2&gt;

&lt;p&gt;One way to get around this issue is to create a symlink from Gatsby's output directory to the static assets directory. First cd into the &lt;code&gt;/my_app/assets/static&lt;/code&gt; directory, and then...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On Unix or Mac:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -s ../gatsby/public blog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;On Windows:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mklink ..\gatsby\public blog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, the entire contents of whatever is generated in Gatsby's public output directory will be visible as a "blog" directory under the Phoenix static assets directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable the blog directory
&lt;/h2&gt;

&lt;p&gt;The final step is to open up &lt;code&gt;endpoint.ex&lt;/code&gt; and update the &lt;code&gt;Plug.Static&lt;/code&gt; portion near the top to allow it to handle the newly created blog directory (which is a symbolic link of the Gatsby public directory). It should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Phoenix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:demo&lt;/span&gt;

  &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="s2"&gt;"/socket"&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;UserSocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;websocket:&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;longpoll:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

  &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;Plug&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Static&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;IndexHtml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;at:&lt;/span&gt; &lt;span class="s2"&gt;"/blog"&lt;/span&gt;

  &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="no"&gt;Plug&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;at:&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;from:&lt;/span&gt; &lt;span class="ss"&gt;:demo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;gzip:&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;only:&lt;/span&gt; &lt;span class="sx"&gt;~w(blog css fonts images js favicon.ico robots.txt)&lt;/span&gt;

  &lt;span class="c1"&gt;# The rest of the file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After saving these changes, and restarting the Phoenix app, the generated Gatsby site is served from within the Phoenix app at &lt;code&gt;localhost:4000/blog/index.html&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible next steps
&lt;/h2&gt;

&lt;p&gt;Now that everything is up and working, You could just build out the web app and static blog. For many apps and sites, no further integration is necessary.&lt;/p&gt;

&lt;p&gt;Here are some ideas, though...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;See if you can write a simple plug that will read the path from &lt;code&gt;conn.request_path&lt;/code&gt; and redirect &lt;code&gt;/blog/&lt;/code&gt; to &lt;code&gt;/blog.index.html&lt;/code&gt;. Or alternatively, you could look at a library &lt;code&gt;plug_static_index_html&lt;/code&gt; and see if you can use it to handle this for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try installing Absinthe GraphQL and serving your static Gatsby blog GraphQL from the Phoenix back-end. This is a fairly large endeavor, but it's a great learning experience!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Request a free email-based Elixir course from &lt;a href="https://alchemist967856.typeform.com/to/FA0SUF"&gt;Alchemist.Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>setup</category>
      <category>phoenix</category>
      <category>staticassets</category>
      <category>gatsby</category>
    </item>
    <item>
      <title>Elixir lists vs Elixir tuples</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Fri, 12 Jul 2019 03:07:16 +0000</pubDate>
      <link>https://dev.to/logicmason/elixir-lists-vs-elixir-tuples-5495</link>
      <guid>https://dev.to/logicmason/elixir-lists-vs-elixir-tuples-5495</guid>
      <description>&lt;p&gt;Along with &lt;a href="https://alchemist.camp/articles/how-to-update-elixir-maps"&gt;maps&lt;/a&gt;, Lists and Tuples are both ubiquitous and somewhat surprising for Elixir learners. Here's a quick guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lists are &lt;em&gt;linked lists&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Elixir lists look just like arrays from C, Java or JavaScript, but they're not. They're not laid out contiguously in memory. They're a series of nodes where each node holds a piece of data and a pointer to the next node. The final node points to nothing.&lt;/p&gt;

&lt;p&gt;This has performance implications. In order to read the final element in a list, you must traverse every element from the head to the tail of the list! Prepending an element to the front of the list is cheap, O(1), but accessing an element at the end is O(n)&lt;/p&gt;

&lt;h3&gt;
  
  
  Tuples are more like Arrays
&lt;/h3&gt;

&lt;p&gt;Elixir tuples are stored contiguously in memory. Accessing any element is O(1). On the down-side, inserting or deleting an element involves copying the entire tuple, which is O(n). Remember, like everything else in the language, Tuples are immutable!&lt;/p&gt;

&lt;h3&gt;
  
  
  List elements are &lt;em&gt;usually&lt;/em&gt; of the same type
&lt;/h3&gt;

&lt;p&gt;This is more of a convention than a rule. Since lists implement the &lt;code&gt;Enumerable&lt;/code&gt; protocol and it's very common to use functions like &lt;code&gt;Enum.map&lt;/code&gt;, &lt;code&gt;Enum.reduce&lt;/code&gt; and &lt;code&gt;Enum.each&lt;/code&gt; that pass each element into a function, life is easier if everything in the list has the same shape.&lt;/p&gt;

&lt;p&gt;Tuples, on the other hand are very often mixed types. They're commonly returned from functions and pattern matched against and in this case the first element is usually a status. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;retrieve_stuff&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;stuff&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;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&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;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Error with message: %{msg}"&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;h3&gt;
  
  
  Converting lists and tuples is easy
&lt;/h3&gt;

&lt;p&gt;You can convert a list to a tuple with &lt;code&gt;List.to_tuple(some_list)&lt;/code&gt; and you can convert a tuple to a list with &lt;code&gt;Tuple.to_list(some_tuple)&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;my_list&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;my_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:c&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;other_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# equals {1, 2, 3}&lt;/span&gt;
&lt;span class="n"&gt;other_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Tuple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_tuple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# equals [:a, :b, :c]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  Common questions
&lt;/h2&gt;

&lt;h4&gt;
  
  
  How do I get the nth element of a list?
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;Enum.at/2&lt;/code&gt;. For example, &lt;code&gt;Enum.at([1, 2, 3, 4], 2)&lt;/code&gt; will return &lt;code&gt;3&lt;/code&gt; since lists are zero-indexed.&lt;/p&gt;

&lt;h4&gt;
  
  
  How do I get the nth element of a tuple?
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;Kernel.elem/2&lt;/code&gt;. For example, &lt;code&gt;elem({:a, :b, :c}, 0)&lt;/code&gt; will return &lt;code&gt;:a&lt;/code&gt; since tuples are also zero-indexed.&lt;/p&gt;

&lt;h4&gt;
  
  
  How do I insert an element into a list?
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;List.insert_at/3&lt;/code&gt;. For example, &lt;code&gt;List.insert_at([:foo, :bar, :baz], 1, :yolo)&lt;/code&gt; returns &lt;code&gt;[:foo, :yolo, :bar, :baz]&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You can delete elements in the same way with &lt;code&gt;List.delete_at/2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you're prepending to the beginning of a list (which is very performant), then you can also use a cons syntax and insert an element like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;my_list&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# returns [:hello, 1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  How do I insert an element into a tuple?
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;Tuple.insert_at/3&lt;/code&gt;. For example, &lt;code&gt;Tuple.insert_at({:ok, :stuff}, 1, :yolo)&lt;/code&gt; returns &lt;code&gt;{:ok, :yolo, :stuff}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can delete elements in the same way with &lt;code&gt;Tuple.delete_at/2&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  How do I get the length of a list or a tuple?
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;Kernel.tuple_size/1&lt;/code&gt; for tuples and use &lt;code&gt;Enum.count/1&lt;/code&gt; for lists.&lt;/p&gt;

&lt;h4&gt;
  
  
  What's a good reference if I need to know more?
&lt;/h4&gt;

&lt;p&gt;It's best to go straight to the official docs!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/elixir/List.html"&gt;Elixir docs: Lists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/elixir/Tuple.html"&gt;Elixir docs: Tuples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Request a free email-based Elixir course from &lt;a href="https://alchemist967856.typeform.com/to/FA0SUF"&gt;Alchemist.Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>elixirlists</category>
      <category>elixirtuples</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Elixir maps made effortless</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Tue, 09 Jul 2019 07:56:06 +0000</pubDate>
      <link>https://dev.to/logicmason/elixir-maps-made-effortless-5cci</link>
      <guid>https://dev.to/logicmason/elixir-maps-made-effortless-5cci</guid>
      <description>&lt;p&gt;Getting used to working with Elixir maps can be one of the most painful aspects of really getting comfortable with the language. If you're coming from a language like Java or Ruby, the fact that everything is immutable can be frustrating to deal with. If you're coming from JavaScript, you'll have that problem &lt;em&gt;and&lt;/em&gt; be spoiled by having native maps (Objects, in JS speak) fit perfectly with JSON.&lt;/p&gt;

&lt;p&gt;The good news is, there are really only a couple of points that trip people up!&lt;/p&gt;

&lt;h2&gt;
  
  
  Variables are immutable in Elixir
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// JavaScript&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;   &lt;span class="c1"&gt;// equals 42&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;   &lt;span class="c1"&gt;// equals {foo: 5}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Elixir&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;foo:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;   &lt;span class="c1"&gt;# equals 42&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;   &lt;span class="c1"&gt;# b and b.foo are immutable so we get an error&lt;/span&gt;
&lt;span class="c1"&gt;# ** (CompileError) iex:5: cannot invoke remote function b.foo/0 inside a match&lt;/span&gt;

&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ss"&gt;foo:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;   &lt;span class="c1"&gt;# now b is reassigned and bound to %{foo: 5}&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;   &lt;span class="c1"&gt;# still equals 42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;h3&gt;
  
  
  All "updating" of maps involves reassigning a variable to a new map
&lt;/h3&gt;

&lt;p&gt;Here are a few common ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;put&lt;/strong&gt; adds a new value to a map: &lt;code&gt;a = Map.put(a, bar: 5)&lt;/code&gt; 
Now a is &lt;code&gt;%{foo: 42, bar: 5}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;delete&lt;/strong&gt; removes a value from a map: &lt;code&gt;a = Map.delete(a, :foo)&lt;/code&gt; 
Now a is &lt;code&gt;%{bar: 5}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;put_new&lt;/strong&gt; works like put, but does nothing if the key already exists: &lt;code&gt;a = Map.put_new(a, :bar, 10)&lt;/code&gt; 
Doesn't replace the existing key, so a is still &lt;code&gt;%{bar: 5}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;merge&lt;/strong&gt; adds/updates multiple values into a map:  &lt;code&gt;a = Map.merge(a, %{foo: "stuff", baz: -5})&lt;/code&gt; 
Now a is &lt;code&gt;%{foo: "stuff", bar: 5, baz: -5}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that since Elixir variables are immutable, the map functions above created new maps instead of changing &lt;code&gt;a&lt;/code&gt; itself. Without reassigning a to the new maps with the &lt;code&gt;a =&lt;/code&gt; at the front of each of the examples above, a would be unchanged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Map keys can be Strings or Atoms (or anything!)
&lt;/h3&gt;

&lt;p&gt;In Elixir, you'll run into two forms of map keys. Some, like the examples above, are atoms and some are strings. Very rarely, you may find integers, floats or even other types, including nested maps used as keys of maps!&lt;/p&gt;

&lt;p&gt;The following are all valid maps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a = %{:some_atom =&amp;gt; :foo}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i = %{1 =&amp;gt; 52}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f = %{1.5 =&amp;gt; i}&lt;/code&gt; - the value of f is now: &lt;code&gt;%{1.5 =&amp;gt; %{1 =&amp;gt; 52}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;m = %{f =&amp;gt; "wat???"}&lt;/code&gt; - the value of m is now: &lt;code&gt;%{%{1.5 =&amp;gt; %{1 =&amp;gt; 52}} =&amp;gt; "wat???"}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Strings&lt;/strong&gt; are the same thing as Erlang binaries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They're represented with quotes. 
&lt;code&gt;"foo"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Longer strings or strings with quotation marks in them can be made with sigils  
&lt;code&gt;~s{I'm a string made from a sigil and can have "quoted" parts}&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;In a &lt;strong&gt;key-value form&lt;/strong&gt;, string keys use an arrow syntax. 
&lt;code&gt;%{"foo" =&amp;gt; "stuff", "bar" =&amp;gt; 5}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When being used to &lt;strong&gt;access&lt;/strong&gt; values, they use a bracket syntax. 
&lt;code&gt;a["foo"]&lt;/code&gt; is "stuff" and &lt;code&gt;b["foo"]&lt;/code&gt; is 5 
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Atoms&lt;/strong&gt; are unique symbols. They don't get garbage collected so don't generate them dynamically.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When represented &lt;strong&gt;alone&lt;/strong&gt;, they start with a colon. 
&lt;code&gt;:foo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In a &lt;strong&gt;key-value form&lt;/strong&gt;, they can use the standard arrow syntax &lt;em&gt;or&lt;/em&gt; simply have a trailing colon. 
&lt;code&gt;%{foo: "stuff, bar: 5}&lt;/code&gt; is the same as &lt;code&gt;%{:foo =&amp;gt; "stuff", :bar =&amp;gt; 5}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When being used to &lt;strong&gt;access&lt;/strong&gt; values, they can use a dot syntax. 
&lt;code&gt;a.foo&lt;/code&gt; is the same as &lt;code&gt;a[:foo]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Working with deeply nested maps
&lt;/h3&gt;

&lt;p&gt;The above techniques are enough to do anything with Elixir maps, however immutability makes working with deeply nested maps a bit cumbersome. Intermediate steps would be required to build up the exact structure you want to reassign a given variable to.&lt;/p&gt;

&lt;p&gt;Of course you're always free to write your own helpers, but for the 90% case, the built-in &lt;code&gt;get_in&lt;/code&gt;, &lt;code&gt;put_in&lt;/code&gt; and related functions will do the job. They're part of Kernel, not Map, because they also operate on other types of data, so they don't have a &lt;code&gt;Map.&lt;/code&gt; prefix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
  &lt;span class="s2"&gt;"sam"&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;age:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"pat"&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;age:&lt;/span&gt; &lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;get_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sam"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# returns 22&lt;/span&gt;

&lt;span class="n"&gt;put_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"pat"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# returns %{"sam" =&amp;gt; "{age: 22}, "pat" =&amp;gt; %{age: 28}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Request a free email-based Elixir course from &lt;a href="https://alchemist967856.typeform.com/to/FA0SUF"&gt;Alchemist.Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>maps</category>
      <category>beginners</category>
      <category>immutability</category>
    </item>
    <item>
      <title>ASDF, the version manager for all your languages </title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Mon, 13 May 2019 16:54:19 +0000</pubDate>
      <link>https://dev.to/logicmason/asdf-the-package-manager-for-all-your-languages-2omg</link>
      <guid>https://dev.to/logicmason/asdf-the-package-manager-for-all-your-languages-2omg</guid>
      <description>&lt;h2&gt;
  
  
  Why use ASDF?
&lt;/h2&gt;

&lt;p&gt;ASDF is a version manager for programming languages. It's somewhat like RVM is for Ruby or NVM is for Node but it also supports Erlang, Elixir, Haskel, Ocaml, PHP, Python, Rust and many other languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prereqs
&lt;/h2&gt;

&lt;p&gt;This guide assumes you have homebrew and Xcode command line tools and nothing else. To see the setup of those from a fresh macOS Mojave install, see &lt;a href="https://youtu.be/Og4L5ijxqpA"&gt;this short video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/YuOnN2bVeFY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone the repo
&lt;/h2&gt;

&lt;p&gt;The ASDF repo page on will have directions for cloning the newest repo github: &lt;a href="https://github.com/asdf-vm/asdf"&gt;https://github.com/asdf-vm/asdf&lt;/a&gt;&lt;/p&gt;



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



&lt;p&gt;Next, add it to your shell:&lt;/p&gt;



&lt;div class="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;Restart your shell (or just open a new tab to work from) and run &lt;code&gt;asdf&lt;/code&gt; to verify that it's installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the plugin dependencies
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install \
  coreutils automake autoconf openssl \
  libyaml readline libxslt libtool unixodbc \
  unzip curl gpg wxmac
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;asdf plugin-list-all&lt;/code&gt;: shows all the plugins (i.e., languages) available&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;asdf plugin-add &amp;lt;language&amp;gt;&lt;/code&gt;: installs &lt;em&gt;language&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;asdf list-all &amp;lt;language&amp;gt;&lt;/code&gt;: shows all available versions of &lt;em&gt;language&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;asdf list &amp;lt;language&amp;gt;:&lt;/code&gt; shows all installed versions of &lt;em&gt;language&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;asdf install &amp;lt;language&amp;gt; &amp;lt;version&amp;gt;&lt;/code&gt;: &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;asdf current&lt;/code&gt;: shows currently enabled languages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;asdf global &amp;lt;language&amp;gt; &amp;lt;version&amp;gt;&lt;/code&gt;: enables the chosen version of a language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## Installing Node&lt;br&gt;
Node requires an extra step:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bash ~/.asdf/plugins/nodejs/bin/import-release-team-keyring
asdf plugin-add nodejs
asdf list-all nodejs
asdf install nodejs &amp;lt;version&amp;gt;
asdf global nodejs &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;## Installing Erlang&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf plugin-add erlang
asdf list-all erlang
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;According the readme on &lt;a href="https://github.com/asdf-vm/asdf-erlang"&gt;the ASDF Erlang plugin repo&lt;/a&gt; we need to pass a couple of flags to the install command:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export KERL_CONFIGURE_OPTIONS="--disable-debug --without-javac"
asdf install erlang &amp;lt;version&amp;gt;
asdf global erlang &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing Elixir
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf plugin-add elixir
asdf list-all elixir
asdf install elixir &amp;lt;version&amp;gt;
asdf global elixir &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing Ruby
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf plugin-add ruby
asdf list-all ruby
asdf install ruby &amp;lt;version&amp;gt;
asdf global ruby &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Verify you have what you need
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf current
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing the Phoenix Framework
&lt;/h2&gt;

&lt;p&gt;If you're reading this on &lt;a href="https://alchemist.camp"&gt;Alchemist Camp&lt;/a&gt;, you're likely using ASDF for Elixir and also want to set up Phoenix:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix local.hex
mix archive.install hex phx_new 1.4.5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Done!
&lt;/h2&gt;

&lt;p&gt;ASDF is a very handy tool for setting up dev machines and keeping the versions of whichever languages you may need. It's a big improvement to have one unified tool over several language specific ones.&lt;/p&gt;

&lt;p&gt;ASDF also supports per-project configuration via &lt;code&gt;.tool-versions&lt;/code&gt; files and a number of other things not covered in this setup guide.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://alchemist.camp/episodes/asdf-language-versions"&gt;Alchemist Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>asdf</category>
      <category>elixir</category>
      <category>erlang</category>
      <category>packagemanager</category>
    </item>
    <item>
      <title>Deploying a Phoenix app to Heroku</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Sat, 11 May 2019 12:56:44 +0000</pubDate>
      <link>https://dev.to/logicmason/deploying-a-phoenix-app-to-heroku-3clf</link>
      <guid>https://dev.to/logicmason/deploying-a-phoenix-app-to-heroku-3clf</guid>
      <description>&lt;p&gt;In this quick guide, we'll build a new Phoenix app, set up Heroku and deploy! Heroku may not be the ideal choice for an Elixir app but Elixir and Phoenix is an ideal stack to run on Heroku!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Wwlz5zGgtFA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you haven't already installed and set up Elixir on your computer, go through the setup part of &lt;a href="https://alchemist.camp/episodes/guessing-game"&gt;lesson 1&lt;/a&gt; and then you'll be ready to follow along here. These are the steps we'll go over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign up for Heroku (&lt;a href="https://signup.heroku.com/"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Install the Heroku Toolbelt (&lt;a href="https://toolbelt.heroku.com/"&gt;download here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Create a new Phoenix app&lt;/li&gt;
&lt;li&gt;Create a new app for it on Heroku&lt;/li&gt;
&lt;li&gt;Add the Phoenix static buildpack&lt;/li&gt;
&lt;li&gt;Create a free tier database on Heroku&lt;/li&gt;
&lt;li&gt;Change some settings in our project&lt;/li&gt;
&lt;li&gt;Make a &lt;code&gt;Procfile&lt;/code&gt; and &lt;code&gt;elixir_buildpack.config&lt;/code&gt; for Heroku&lt;/li&gt;
&lt;li&gt;Push everything to Heroku to deploy!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;We'll call our app &lt;code&gt;Hello&lt;/code&gt;, so here's what we need to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mix phx.new hello
&lt;span class="nb"&gt;cd &lt;/span&gt;hello
git init
heroku create &lt;span class="nt"&gt;--buildpack&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/HashNuke/heroku-buildpack-elixir.git"&lt;/span&gt;
heroku buildpacks:add https://github.com/gjaldon/heroku-buildpack-phoenix-static.git
heroku addons:create heroku-postgresql:hobby-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Application files to change
&lt;/h2&gt;

&lt;p&gt;Heroku stores secrets in system environment variables instead of a secrets file, so we can delete &lt;code&gt;prod.secrets.exs&lt;/code&gt;. Then, we can update &lt;code&gt;prod.exs&lt;/code&gt; to get the secrets we need from &lt;code&gt;System.get_env&lt;/code&gt;. While we're there we can also set the app to use SSL and update the host name to whatever Heroku named our app when we created it. Finally add the database settings to the bottom of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;HelloWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;load_from_system_env:&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;url:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;scheme:&lt;/span&gt; &lt;span class="s2"&gt;"https"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;host:&lt;/span&gt; &lt;span class="s2"&gt;"NAME_OF_HEROKU_APP.herokuapp.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;port:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;force_ssl:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;rewrite_on:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:x_forwarded_proto&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
  &lt;span class="ss"&gt;cache_static_manifest:&lt;/span&gt; &lt;span class="s2"&gt;"priv/static/cache_manifest.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;secret_key_base:&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s2"&gt;"SECRET_KEY_BASE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Do not print debug messages in production&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;level:&lt;/span&gt; &lt;span class="ss"&gt;:info&lt;/span&gt;

&lt;span class="c1"&gt;# Configure your database&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;adapter:&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;Adapters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Postgres&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;pool_size:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"POOL_SIZE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"10"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;ssl:&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;url:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If your app is going to use channels, then update your &lt;code&gt;user_socket.ex&lt;/code&gt; file to add a timeout for sockets. Heroku limits them to 55 seconds, so set the time out to something like 45 seconds to be safe:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;transport(:websocket, Phoenix.Transports.WebSocket, timeout: 45_000)&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Application settings for Heroku
&lt;/h2&gt;

&lt;p&gt;By default Phoenix uses a pool size of 10. This is very low and ideally we want to use nearly as much as is available. On Heroku we have a maximum pool of 20, so we'll set our application to use 18 and just use 2 for mix tasks. We'll also generate a secret key with Phoenix and set that in Heroku so that the app can get it from the system environment in production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku config:set &lt;span class="nv"&gt;POOL_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;18
heroku run &lt;span class="s2"&gt;"POOL_SIZE=2 mix hello.task"&lt;/span&gt;
mix phx.gen.secret
heroku config:set &lt;span class="nv"&gt;SECRET_KEY_BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;SECRET PHOENIX JUST GENERATED ABOVE&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  New files to add
&lt;/h2&gt;

&lt;p&gt;In the root directory of our app, we'll add two more files for Heroku—one called &lt;code&gt;Procfile&lt;/code&gt; that has just one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web: MIX_ENV=prod mix phx.server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and one called &lt;code&gt;elixir_buildpack.config&lt;/code&gt; that holds some configuration settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;erlang_version=20.1
elixir_version=1.7.2
always_rebuild=false
runtime_path=/app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Make sure that both files have LF line endings. Heroku throws errors on CRLF!&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy!
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"prepares for heroku"&lt;/span&gt;
git push heroku master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://alchemist.camp/episodes/deploy-phoenix-heroku"&gt;Alchemist Camp&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>heroku</category>
      <category>deployment</category>
    </item>
    <item>
      <title>TypeScript libraries with incorrectly typed members</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Sat, 27 Apr 2019 06:44:33 +0000</pubDate>
      <link>https://dev.to/logicmason/typescript-libraries-with-incorrectly-typed-members-1ln7</link>
      <guid>https://dev.to/logicmason/typescript-libraries-with-incorrectly-typed-members-1ln7</guid>
      <description>&lt;p&gt;I recently covered an &lt;a href="https://logicmason.com/2019/how-to-make-typescript-shut-up-about-that-library/" rel="noopener noreferrer"&gt;easy way to silence TypeScript&lt;/a&gt; when dealing with 3rd party libries with missing or incorrect types.&lt;/p&gt;

&lt;p&gt;An additional question that post brought up was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do I get fix TypeScript "namespace has no exported member" errors?&lt;/p&gt;
&lt;/blockquote&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx2107udznzf4ypn6kqnz.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx2107udznzf4ypn6kqnz.png" alt="TypeScript errors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Let's say you're using the popular JavaScript game framework Phaser, which has multiple complex deeply nested objects. The types provided are virtually always out of date with the library itself since Phaser is complex, quickly moving and mostly used by people writing JS rather than TS.&lt;/p&gt;

&lt;p&gt;With an existing TypeScript project, if you've been updating your types as you go, there's no issue. But when you migrate a project from JS to TS, you'll have a lot of errors to work through. Even a new project on the newest version of the framework can be an editor full of red squiggly lines and type errors.&lt;/p&gt;

&lt;p&gt;Worse still, parts your code must refer to members of Phaser. Even if you write &lt;code&gt;declare const Phaser: any;&lt;/code&gt; at the top of your app to silence all TS errors from importing or using Phaser, you've still got two problems. First, it's overkill and you probably do want to get your app typed, including the Phaser portions at some point. Second, you're probably going to make your own class which has a member of type &lt;code&gt;Phaser.Game&lt;/code&gt;. Since &lt;code&gt;Phaser.Game&lt;/code&gt; is also very complex and generally ships with incomplete or out of date types, you'll end up with with the "namespace has no exported member error".&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;Work from the outside of your 3rd party library in. Disable warnings on member types &lt;em&gt;by exporting their types in the 3rd party library's namespace&lt;/em&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="nx"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;Phaser&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Game&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyGame&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;actors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyActorType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyActorType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Phaser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// TS errors are silenced here now!&lt;/span&gt;
    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;manageAssets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// ... the rest of the MyGame class&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you'll no longer get the error about Phaser.Game. In other modules, where you use members of &lt;code&gt;Game&lt;/code&gt;, you can dig deeper with the same process if there are further nested type issues. Eventually you'll get down to simple objects that are trivial to correctly type.&lt;/p&gt;

&lt;p&gt;Fixing these issues as you go, you'll get to a point where all the parts in of the 3rd party library &lt;em&gt;that are used in your app&lt;/em&gt; will be correctly typed and the others will be silenced. This is a reasonable trade-off with a large 3rd party library in flux, such as Phaser or Materialize.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Subscribe to more content from &lt;a href="http://eepurl.com/diFSaf" rel="noopener noreferrer"&gt;logicmason.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>refactoring</category>
      <category>typescript</category>
    </item>
    <item>
      <title>setTimeout vs setImmediate vs process.nextTick</title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Mon, 22 Apr 2019 03:23:45 +0000</pubDate>
      <link>https://dev.to/logicmason/settimeout-vs-setimmediate-vs-process-nexttick-3lj2</link>
      <guid>https://dev.to/logicmason/settimeout-vs-setimmediate-vs-process-nexttick-3lj2</guid>
      <description>&lt;p&gt;What's the difference between &lt;code&gt;setTimeout(callback, 0)&lt;/code&gt; and &lt;code&gt;process.nextTick(callback)&lt;/code&gt;? How about Node's &lt;code&gt;setImmediate(callback)&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;On the surface it appears that all three functions do the same thing—they execute the callback after the current event loop, but before anything else. The natural question to ask is, why are there three different functions? Let's run an experiment:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;racer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timeout"&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="nx"&gt;setImmediate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"immediate"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextTick&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nextTick"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"current event loop"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;racer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can see from the output that these callbacks aren't executed in the same order they were written in the source code.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="s2"&gt;"/Users/logicmason/timeouts.js"&lt;/span&gt;
&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="nx"&gt;loop&lt;/span&gt;
&lt;span class="nx"&gt;nextTick&lt;/span&gt;
&lt;span class="nx"&gt;timeout&lt;/span&gt;
&lt;span class="nx"&gt;immediate&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nx"&gt;exited&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;0.203&lt;/span&gt; &lt;span class="nx"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;p&gt;The first one executed was &lt;code&gt;process.nextTick&lt;/code&gt;, which puts its callback at the front of the event queue. It will execute after the code currently being executed but before any I/O events or timers.&lt;/p&gt;

&lt;p&gt;Next is "timeout". Since we passed &lt;code&gt;setTimeout&lt;/code&gt; a timeout of 0, there's no additional enforced delay before its execution, and it is placed on into the timer queue during the next loop.&lt;/p&gt;

&lt;p&gt;Finally, we have &lt;code&gt;setImmediate&lt;/code&gt;, which is clearly not as immediate as its name suggests! Its callback is placed in the check queue of the next cycle of the event loop. Since the check queue occurs later than the timer queue, setImmediate will be slower than setTimeout 0.&lt;/p&gt;

&lt;p&gt;All in all, the event loop looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;timers&lt;/code&gt; -&amp;gt; &lt;code&gt;IO&lt;/code&gt; -&amp;gt; &lt;code&gt;poll&lt;/code&gt; -&amp;gt; &lt;code&gt;check&lt;/code&gt; -&amp;gt;&lt;code&gt;close&lt;/code&gt; -&amp;gt; &lt;code&gt;timers&lt;/code&gt; -&amp;gt; ...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timers&lt;/strong&gt;: callbacks from &lt;code&gt;setInterval&lt;/code&gt; or &lt;code&gt;setTimeout&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;IO callbacks&lt;/strong&gt;: callbacks from I/O events&lt;br&gt;
&lt;strong&gt;Idle&lt;/strong&gt;: used internally by Node between IO and Poll phases&lt;br&gt;
&lt;strong&gt;Poll&lt;/strong&gt;: retrieve new I/O events&lt;br&gt;
&lt;strong&gt;Check&lt;/strong&gt;: callbacks from &lt;code&gt;setImmediate&lt;/code&gt; execute here&lt;br&gt;
&lt;strong&gt;Close&lt;/strong&gt;: handle closed connections like sockets&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge time!
&lt;/h3&gt;

&lt;p&gt;What do you expect the output of the following code in Node to be?&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;racer1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timeout"&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="nx"&gt;setImmediate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"immediate"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextTick&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nextTick"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;racer2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextTick&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nextTick"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timeout"&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="nx"&gt;setImmediate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"immediate"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;racer3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setImmediate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"immediate"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextTick&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nextTick"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timeout"&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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;racer1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;racer2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;racer3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Was it what you expected?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Subscribe to more content from &lt;a href="http://eepurl.com/diFSaf"&gt;logicmason.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>eventloop</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to make TypeScript shut up about that library </title>
      <dc:creator>Mark</dc:creator>
      <pubDate>Fri, 19 Apr 2019 15:56:06 +0000</pubDate>
      <link>https://dev.to/logicmason/how-to-make-typescript-shut-up-about-that-library-4jd3</link>
      <guid>https://dev.to/logicmason/how-to-make-typescript-shut-up-about-that-library-4jd3</guid>
      <description>&lt;p&gt;April 14, 2019&lt;/p&gt;

&lt;p&gt;TypeScript is a tradeoff.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I use typescript when I feel like having hours of migraines using 3rd party libraries and making sure I don’t have a single space or comma out of place! Works like a charm! Get a headache 10/10 times.”&lt;/p&gt;

&lt;p&gt;-somebody on Reddit&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;TypeScript can do wonders for your code editor’s ability to help you with auto-completions, it can enforce contracts between different parts of your code base in the way documentation never could, and it can help a large team move faster.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx2107udznzf4ypn6kqnz.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx2107udznzf4ypn6kqnz.png" alt="TypeScript errors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can also drive you to the point of madness when dealing with its increasingly pedantic compiler, especially when dealing with third party libraries that have incomplete, incorrect or conflicting types.&lt;/p&gt;

&lt;p&gt;In general, it’s good to type as much as possible so you get the benefits TS offers. But how do you silence compiler warnings when it’s not your code and the upstream library just isn’t typed correctly?&lt;/p&gt;

&lt;p&gt;You can add this to your codebase:&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="nx"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;annoyingLibrary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then the TypeScript compiler will stop complaining about &lt;code&gt;annoyingLibrary&lt;/code&gt; types.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://logicmason.com/2019/how-to-make-typescript-shut-up-about-that-library/" rel="noopener noreferrer"&gt;logicmason.com&lt;/a&gt; on April 14, 2019.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kludge</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
