<?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: Alex Sharp 🛠sharesecret.co</title>
    <description>The latest articles on DEV Community by Alex Sharp 🛠sharesecret.co (@ajsharp).</description>
    <link>https://dev.to/ajsharp</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%2F131709%2F67864a9f-8ef2-42aa-8547-523e3a71c259.jpg</url>
      <title>DEV Community: Alex Sharp 🛠sharesecret.co</title>
      <link>https://dev.to/ajsharp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ajsharp"/>
    <language>en</language>
    <item>
      <title>JSON Parsing with Go Embedded Structs</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Thu, 11 Jun 2020 21:48:42 +0000</pubDate>
      <link>https://dev.to/ajsharp/json-parsing-with-go-embedded-structs-3f8o</link>
      <guid>https://dev.to/ajsharp/json-parsing-with-go-embedded-structs-3f8o</guid>
      <description>&lt;p&gt;Go has a feature called &lt;a href="https://golang.org/doc/effective_go.html#embedding"&gt;embedding&lt;/a&gt; that allows you to create higher level interfaces by combining existing interfaces. But embedding can also be applied to structs, which is very useful for JSON parsing/decoding.&lt;/p&gt;

&lt;p&gt;Consider the common case of decoding JSON objects that have a timestamp field, in this case encoded as a unix integer timestamp, as JSON has no native date support (this same solution could be applied to a iso-8601 encoded date string).&lt;/p&gt;

&lt;p&gt;Here's a &lt;code&gt;PriceTick&lt;/code&gt; json object and struct that will decode but isn't quite what we want. Ideally we want &lt;code&gt;Timestamp&lt;/code&gt; to be a &lt;code&gt;time.Time&lt;/code&gt; object rather than an &lt;code&gt;int64&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1591745820&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;321.655&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;321.68&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;321.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;321.61&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"close"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;321.61&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"volume"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2608&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vwap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;321.66511&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PriceTick&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Timestamp&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;     &lt;span class="s"&gt;`json:"timestamp"`&lt;/span&gt;
    &lt;span class="n"&gt;Price&lt;/span&gt;     &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"price"`&lt;/span&gt;
    &lt;span class="n"&gt;Volume&lt;/span&gt;    &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"volume"`&lt;/span&gt;
    &lt;span class="n"&gt;Open&lt;/span&gt;      &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"open"`&lt;/span&gt;
    &lt;span class="n"&gt;High&lt;/span&gt;      &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"high"`&lt;/span&gt;
    &lt;span class="n"&gt;Low&lt;/span&gt;       &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"low"`&lt;/span&gt;
    &lt;span class="n"&gt;Close&lt;/span&gt;     &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"close"`&lt;/span&gt;
    &lt;span class="n"&gt;VWAP&lt;/span&gt;      &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"vwap"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Go lets you do custom json decoding on an object by defining the &lt;code&gt;UnmarshalJSON&lt;/code&gt; interface method on a struct. But we don't want to do it for the entire &lt;code&gt;PriceTick&lt;/code&gt; object, just the timestamp property.&lt;/p&gt;

&lt;p&gt;We can define a custom &lt;code&gt;Timestamp&lt;/code&gt; struct to hold the time object, but then you have to dig into the object whenever you want to access the &lt;code&gt;time.Time&lt;/code&gt; object it's holding, which is not ideal if we want to replicate the native object structure we're reading from JSON.&lt;/p&gt;

&lt;p&gt;This is where embedded structs shine.&lt;/p&gt;

&lt;p&gt;We can modify the definition above to point to a struct that effectively wraps a &lt;code&gt;time.Time&lt;/code&gt; object, and only do custom json decoding on that object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Timestamp wraps a time object encoded as a int64 unix timestamp&lt;/span&gt;
&lt;span class="c"&gt;// This can be used in structs and it automatically handles decoding&lt;/span&gt;
&lt;span class="c"&gt;// int64 unix timestamps into a time.Time object.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Timestamp&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// PriceTick is a tick returned from the TimeAndSales endpoint&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PriceTick&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Timestamp&lt;/span&gt; &lt;span class="n"&gt;Timestamp&lt;/span&gt; &lt;span class="s"&gt;`json:"timestamp"`&lt;/span&gt;
    &lt;span class="n"&gt;Time&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="s"&gt;`json:"time"`&lt;/span&gt;
    &lt;span class="n"&gt;Price&lt;/span&gt;     &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"price"`&lt;/span&gt;
    &lt;span class="n"&gt;Volume&lt;/span&gt;    &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"volume"`&lt;/span&gt;
    &lt;span class="n"&gt;Open&lt;/span&gt;      &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"open"`&lt;/span&gt;
    &lt;span class="n"&gt;High&lt;/span&gt;      &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"high"`&lt;/span&gt;
    &lt;span class="n"&gt;Low&lt;/span&gt;       &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"low"`&lt;/span&gt;
    &lt;span class="n"&gt;Close&lt;/span&gt;     &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"close"`&lt;/span&gt;
    &lt;span class="n"&gt;VWAP&lt;/span&gt;      &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="s"&gt;`json:"vwap"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// UnmarshalJSON decodes an int64 timestamp into a time.Time object&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;UnmarshalJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// 1. Decode the bytes into an int64&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error decoding timestamp: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// 2 - Parse the unix timestamp&lt;/span&gt;
    &lt;span class="o"&gt;*&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By embedding the &lt;code&gt;time.Time&lt;/code&gt; property in the &lt;code&gt;Timestamp&lt;/code&gt; struct without a property name, we can call any &lt;code&gt;time.Time&lt;/code&gt; methods directly on a Timestamp object.&lt;/p&gt;

&lt;p&gt;From the Go documentation on embedding:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When we embed a type, the methods of that type become methods of the outer type, but when they are invoked the receiver of the method is the inner type, not the outer one.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>go</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>A Disabled React Component</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Thu, 07 May 2020 09:04:37 +0000</pubDate>
      <link>https://dev.to/ajsharp/a-disabled-react-component-4k3p</link>
      <guid>https://dev.to/ajsharp/a-disabled-react-component-4k3p</guid>
      <description>&lt;p&gt;Fairly often in a React app you need to disable a component based on a prop or some state. Using a &lt;code&gt;Disabled&lt;/code&gt; component is a clean and reusable way to handle that conditional logic.&lt;/p&gt;

&lt;p&gt;You could choose to implement disabled by not showing the component at all (eg setting &lt;code&gt;display: none&lt;/code&gt;), or you can do as I've done here and change the opacity to gray out the component. Most importantly, you can easily disable click events by setting the &lt;code&gt;pointerEvents&lt;/code&gt; css property to &lt;code&gt;none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/j60s4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>todayilearned</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Automatically Assign Elastic IPs to Elastic Beanstalk Instances</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Tue, 18 Feb 2020 16:48:17 +0000</pubDate>
      <link>https://dev.to/ajsharp/automatically-assign-elastic-ips-to-elastic-beanstalk-instances-3mhb</link>
      <guid>https://dev.to/ajsharp/automatically-assign-elastic-ips-to-elastic-beanstalk-instances-3mhb</guid>
      <description>&lt;p&gt;I've had a need for a while to automatically assign elastic IP addresses to newly launched Elastic Beanstalk instances. This is super useful if you're using an external database host like Compose, and you only want to allow connections coming from your app instances.&lt;/p&gt;

&lt;p&gt;But when elastic beanstalk brings up a new instance it assigns it a random IP address. The script below solves this, by triggering a lambda function with a Cloudwatch rule when a new EC2 instance is launched.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: This script assumes you have a pool of elastic IPs – it doesn't provision them.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create a Cloudwatch Rule
&lt;/h2&gt;

&lt;p&gt;Create a cloudwatch rule that runs when an EC2 instance transitions to a "running" state, and have it trigger a lambda function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W6GmkyNr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ajsharp.com/content/images/2020/02/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W6GmkyNr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ajsharp.com/content/images/2020/02/image-1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Create the Lambda Function
&lt;/h2&gt;

&lt;p&gt;Paste the following code into a lambda function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ec2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EC2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PROD_ENV_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-prod-env-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Example Event&lt;/span&gt;
&lt;span class="c1"&gt;// {&lt;/span&gt;
&lt;span class="c1"&gt;//   "version": "0",&lt;/span&gt;
&lt;span class="c1"&gt;//   "id": "ee376907-2647-4179-9203-343cfb3017a4",&lt;/span&gt;
&lt;span class="c1"&gt;//   "detail-type": "EC2 Instance State-change Notification",&lt;/span&gt;
&lt;span class="c1"&gt;//   "source": "aws.ec2",&lt;/span&gt;
&lt;span class="c1"&gt;//   "account": "123456789012",&lt;/span&gt;
&lt;span class="c1"&gt;//   "time": "2015-11-11T21:30:34Z",&lt;/span&gt;
&lt;span class="c1"&gt;//   "region": "us-east-1",&lt;/span&gt;
&lt;span class="c1"&gt;//   "resources": [&lt;/span&gt;
&lt;span class="c1"&gt;//     "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111"&lt;/span&gt;
&lt;span class="c1"&gt;//   ],&lt;/span&gt;
&lt;span class="c1"&gt;//   "detail": {&lt;/span&gt;
&lt;span class="c1"&gt;//     "instance-id": "i-abcd1111",&lt;/span&gt;
&lt;span class="c1"&gt;//     "state": "running"&lt;/span&gt;
&lt;span class="c1"&gt;//   }&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EVENT:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// The newly launched instance ID.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instanceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;instance-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch info about the newly launched instance&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describeInstances&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;Filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;instance-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;instanceId&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;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// The instance details are buried in this object&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reservations&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;Instances&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAttached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NetworkInterfaces&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;int&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Association&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IpOwnerId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amazon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Bail if the instance is already attached to another EIP&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAttached&lt;/span&gt;&lt;span class="p"&gt;)&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This instance is already assigned to an elastic IP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&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="c1"&gt;// In elastic beanstalk, the instance name gets assigned to the enviroment name.&lt;/span&gt;
  &lt;span class="c1"&gt;// There is also an environment name tag, which could be used here.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Only assign EIPs to production instances&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;PROD_ENV_NAME&lt;/span&gt;&lt;span class="p"&gt;)&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Not a production instance. Not assigning. Instance name:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&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="c1"&gt;// Get a list of elastic IP addresses&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describeAddresses&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Filter out addresses already assigned to instances&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;availableAddresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Addresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NetworkInterfaceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Raise an error if we have no more available IP addresses&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;availableAddresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&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;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ERROR: no available ip addresses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ERROR: no available ip addresses&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstAvail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;availableAddresses&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Associate the instance to the address&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;associateAddress&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;AllocationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firstAvail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AllocationId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;InstanceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;instanceId&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;promise&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;allocation result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Associated IP address.&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="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ERROR: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&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;p&gt;Whenever your elastic beanstalk environment launches a new instance, the above lambda function will get hit, and if there's an available elastic IP address, it will assign it to the new instance.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
    </item>
    <item>
      <title>Graphql Rails Generators</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Tue, 03 Dec 2019 18:53:32 +0000</pubDate>
      <link>https://dev.to/ajsharp/graphql-rails-generators-34lk</link>
      <guid>https://dev.to/ajsharp/graphql-rails-generators-34lk</guid>
      <description>&lt;p&gt;I recently published some helpful generators for working with graphql in rails. These generators look at your ActiveRecord models and generate model types, input types, and mutations from your ActiveRecord model schema. Enjoy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ajsharp/graphql-rails-generators"&gt;https://github.com/ajsharp/graphql-rails-generators&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>rails</category>
    </item>
    <item>
      <title>Today’s rails security update in plain english</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Thu, 14 Mar 2019 02:31:33 +0000</pubDate>
      <link>https://dev.to/ajsharp/todays-rails-security-update-in-plain-english-5h88</link>
      <guid>https://dev.to/ajsharp/todays-rails-security-update-in-plain-english-5h88</guid>
      <description>&lt;p&gt;&lt;em&gt;Cross-posted from &lt;a href="https://blog.sharesecret.co/todays-rails-security-update-plain-english/"&gt;the ShareSecret blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Earlier today the Rails team &lt;a href="https://weblog.rubyonrails.org/2019/3/13/Rails-4-2-5-1-5-1-6-2-have-been-released/"&gt;pushed new versions&lt;/a&gt; to patch three security vulnerabilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://groups.google.com/forum/#!topic/rubyonrails-security/pFRKI96Sm8Q"&gt;CVE-2019-5418&lt;/a&gt;: Action view file content disclosure&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://groups.google.com/forum/#!topic/rubyonrails-security/GN7w9fFAQela"&gt;CVE-2019-5419&lt;/a&gt;: Action view Denial of Service (DOS)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://groups.google.com/forum/#!topic/rubyonrails-security/IsQKvDqZdKw"&gt;CVE-2019-5420&lt;/a&gt;: Rails development mode Remote code execution (RCE)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’ve addressed the vulnerabilities below in order of severity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: The &lt;a href="https://guides.rubyonrails.org/upgrading_ruby_on_rails.html"&gt;rails upgrade guide&lt;/a&gt; is a great resource for upgrading your rails app.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 🚨 🚨 🚨 🚨 🔥 Action View Denial of Service (DOS)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Alarm level:&lt;/strong&gt; Five alarm fire. Patch immediately.&lt;/p&gt;

&lt;p&gt;If you’re rendering tempates, you’re almost definitely subject to a DOS attack. This one is really bad. Patch/upgrade immediately.&lt;/p&gt;

&lt;p&gt;Using specially crafted headers you can max out the CPU by exploiting the template location code. Rendering templates wrapped in a &lt;code&gt;respond_to&lt;/code&gt; block is safe. Otherwise, you’re vulnerable.&lt;/p&gt;

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

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt; 
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt; 
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"index"&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Not vulnerable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt; 
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt; 
    &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"index"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://groups.google.com/forum/#!topic/rubyonrails-security/GN7w9fFAQeI"&gt;Read more&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 🚨 🚨 🚨 🚨 🔥 Action View File Content Disclosure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Alarm level:&lt;/strong&gt; Five alarm fire. Patch immediately.&lt;/p&gt;

&lt;p&gt;By using specially crafted headers, you can view an arbitrary file’s content with if you use &lt;code&gt;render file: 'filename'&lt;/code&gt;. Not good.&lt;/p&gt;

&lt;p&gt;The good news: if you’re just rendering normal templates, you’re not affected &lt;em&gt;by this vulnerability&lt;/em&gt;, though you’re probably affected by the CVE-2019-5419.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://groups.google.com/forum/#!topic/rubyonrails-security/pFRKI96Sm8Q"&gt;Read more&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 Rails development mode RCE
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Alarm level:&lt;/strong&gt; Not good, but go back to sleep. Fix it in the morning. &lt;/p&gt;

&lt;p&gt;Due to how rails generates the &lt;code&gt;secret_key_base&lt;/code&gt; &lt;strong&gt;in development mode&lt;/strong&gt; — an MD5 of the app module name — if you know the name of the application, you can figure out the secret key. As long as you don’t have dev mode apps exposed to the public, this isn’t a huge deal, though is still something worth fixing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://groups.google.com/forum/#!topic/rubyonrails-security/IsQKvDqZdKw"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;☝️ &lt;em&gt;&lt;strong&gt;Be sure to check out &lt;a href="https://www.sharesecret.co"&gt;Sharesecret&lt;/a&gt;, which makes it easy to securely share sensitive data.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>security</category>
      <category>ruby</category>
    </item>
    <item>
      <title>A simple react date picker component</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Tue, 12 Mar 2019 09:53:53 +0000</pubDate>
      <link>https://dev.to/ajsharp/a-simple-react-date-picker-component-3216</link>
      <guid>https://dev.to/ajsharp/a-simple-react-date-picker-component-3216</guid>
      <description>&lt;p&gt;None of the existing react date picker components quite fit my requirements (mostly too bloated with too many dependencies), so I decided to see if I could quickly hack one together. This took a couple of hours, but should meet my needs. Most importantly, it's tiny (~100 LOC) and free of the complexity of many of the existing solutions.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/ypnwjron0z"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cross-posted from &lt;a href="https://ajsharp.com/a-simple-react-date-picker-component"&gt;ajsharp.com/a-simple-react-date-picker-component/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>react</category>
    </item>
    <item>
      <title>Disabling specific eslint rules</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Mon, 04 Mar 2019 08:10:58 +0000</pubDate>
      <link>https://dev.to/ajsharp/disabling-specific-eslint-rules-56bj</link>
      <guid>https://dev.to/ajsharp/disabling-specific-eslint-rules-56bj</guid>
      <description>&lt;p&gt;The &lt;a href="http://github.com/facebook/create-react-app/"&gt;create react app&lt;/a&gt; eslint presets come with a few rules that are slightly annoying. One of them is jsx-a11y/href-no-hash, which makes sure you don’t add an &lt;a&gt; tag without a valid http address for the href property.&lt;br&gt;
To ignore this, add a .eslintrc.js file at the project root with the following:&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&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;parser&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;babel-eslint&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;env&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;browser&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rules&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;jsx-a11y/anchor-is-valid&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;off&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then make sure to reload the vscode window.&lt;/p&gt;

&lt;p&gt;Full eslint config file documentation &lt;a href="https://eslint.org/docs/user-guide/configuring"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;☝️ &lt;em&gt;&lt;strong&gt;Be sure to check out &lt;a href="https://www.sharesecret.co"&gt;Sharesecret&lt;/a&gt;, which makes it easy to securely share sensitive data.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>react</category>
    </item>
    <item>
      <title>☝️Redux dev tools are a thing and they're incredible</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Fri, 22 Feb 2019 06:42:07 +0000</pubDate>
      <link>https://dev.to/ajsharp/redux-dev-tools-are-a-thing-and-theyre-incredible-2ji5</link>
      <guid>https://dev.to/ajsharp/redux-dev-tools-are-a-thing-and-theyre-incredible-2ji5</guid>
      <description>&lt;p&gt;Today I discovered -- in the spirit of the fantastic &lt;a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en" rel="noopener noreferrer"&gt;React Dev Tools&lt;/a&gt; -- there exists an equally if not more useful &lt;a href="https://github.com/reduxjs/redux-devtools" rel="noopener noreferrer"&gt;Redux Dev Tools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F7957859%2F48663602-3aac4900-ea9b-11e8-921f-97059cbb599c.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%2Fuser-images.githubusercontent.com%2F7957859%2F48663602-3aac4900-ea9b-11e8-921f-97059cbb599c.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few of the things you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An inspectable timeline of every action dispatched by the store&lt;/li&gt;
&lt;li&gt;A state diff for each action. e.g. How each action changed the state object&lt;/li&gt;
&lt;li&gt;A full state inspector&lt;/li&gt;
&lt;li&gt;A test generator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wow. Just, wow.&lt;/p&gt;




&lt;p&gt;☝️ &lt;em&gt;&lt;strong&gt;Be sure to check out &lt;a href="https://www.sharesecret.co" rel="noopener noreferrer"&gt;Sharesecret&lt;/a&gt;, which makes it easy to securely share sensitive data.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>react</category>
      <category>redux</category>
    </item>
    <item>
      <title>The Hilarious Fragility of NLP APIs</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Thu, 21 Feb 2019 19:42:34 +0000</pubDate>
      <link>https://dev.to/ajsharp/the-hilarious-fragility-of-nlp-apis-2api</link>
      <guid>https://dev.to/ajsharp/the-hilarious-fragility-of-nlp-apis-2api</guid>
      <description>&lt;p&gt;Recently I've been working on functionality in &lt;a href="https://www.producthunt.com/upcoming/follow-reset" rel="noopener noreferrer"&gt;Follow Reset&lt;/a&gt; that requires machine learning and natural language processing, so I've been experimenting with two well-known NLP APIs: &lt;a href="https://aws.amazon.com/comprehend/" rel="noopener noreferrer"&gt;AWS Comprehend&lt;/a&gt; and &lt;a href="https://cloud.google.com/natural-language/" rel="noopener noreferrer"&gt;Google Natural Language&lt;/a&gt;. While my primary interest in these API's is for their custom modeling capabilities, I was curious to see what kind of quick results I could get from their basic entity recognition and categorization functionality.&lt;/p&gt;

&lt;p&gt;The high-level product goal is simple: use Twitter bios to extract and detect high-level categorical information about people.&lt;/p&gt;

&lt;p&gt;My main test case is the profile description of &lt;a href="https://twitter.com/joerogan" rel="noopener noreferrer"&gt;Joe Rogan&lt;/a&gt;, a very well-known comedian and podcaster with 4.68M Twitter followers (as of writing).&lt;/p&gt;

&lt;p&gt;My (naive) hope was that these APIs would be able to extract from this description that this person is Joe Rogan, who is a comedian.&lt;/p&gt;

&lt;p&gt;The results were...uh...surprising, to say the least.&lt;/p&gt;

&lt;h2&gt;
  
  
  😕 Initial (odd) results
&lt;/h2&gt;

&lt;p&gt;I used Joe's Twitter bio as the input into both APIs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stand up comic/mixed martial arts fanatic/psychedelic adventurer Host of The Joe Rogan Experience #FreakParty &lt;a href="http://www.facebook.com/JOEROGAN" rel="noopener noreferrer"&gt;http://www.facebook.com/JOEROGAN&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AWS Comprehend recognizes Joe Rogan as a person. Good start. AWS has a feature called key phrase extraction, that unfortunately in this case, doesn't add much context and is in general pretty useless here.&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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AF3kTMW0Hq9R6oSM3K31H1Q.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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AF3kTMW0Hq9R6oSM3K31H1Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google, on the other hand, doesn't actually recognize "Joe Rogan" as a person, though it identifies both "Host" and "mixed martial arts fanatic" as a Person entity. Odd.&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%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2At67Mzs5qckvC0uZLhONpxQ.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%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2At67Mzs5qckvC0uZLhONpxQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While Comprehend's entity results tend to be more factual, (Joe Rogan is a person) Google's results &lt;em&gt;attempt&lt;/em&gt; to provide context, identifying direct contextual entities in his bio like "adventurer", as well as a Wikipedia article about the Joe Rogan Experience - his highly popular podcast - context &lt;em&gt;not contained&lt;/em&gt; in the bio.&lt;/p&gt;

&lt;p&gt;One thing that jumps out here is that while Google identifies categorical context -this is probably the description of a comic - it is unable to properly identify the Person entity to which the comic category refers. Considering Google's ability to detect and suggest context that is external to the input string, it's a bit of a head-scratcher that it fails to correctly identify the Person entity.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 Changing the Inputs, Content is Key?
&lt;/h2&gt;

&lt;p&gt;What happens if we change the name from Joe Rogan to Alex Sharp?&lt;/p&gt;

&lt;p&gt;Here's the updated input string:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stand up comic/mixed martial arts fanatic/psychedelic adventurer Host of The Alex Sharp Experience #FreakParty &lt;a href="http://www.facebook.com/AlexSharp" rel="noopener noreferrer"&gt;http://www.facebook.com/AlexSharp&lt;/a&gt;&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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AShfIAZeHyepI0EUk4KJNWw.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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AShfIAZeHyepI0EUk4KJNWw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Amazon's still sees Alex Sharp as a person entity. Cool. I am that. 🙋‍♂️&lt;/p&gt;

&lt;p&gt;Google's results are…unexpected. Somehow, Google is &lt;strong&gt;more confident&lt;/strong&gt; that Alex Sharp is a Comic than Joe Rogan. Uh, sure 😂&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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A_NDLh55IHVbCn-Wn67MY9Q.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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A_NDLh55IHVbCn-Wn67MY9Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🙃 joe rogan is not Joe Rogan?
&lt;/h2&gt;

&lt;p&gt;What happens if you de-capitalize &lt;em&gt;Joe Rogan&lt;/em&gt; to &lt;em&gt;joe rogan&lt;/em&gt;? When we do this, Amazon no longer recognizes the person entity. Google still thinks we're &lt;em&gt;probably&lt;/em&gt; talking about a comic, but not by much.&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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AzDyfKp0glaKF30HMfmF-Fw.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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AzDyfKp0glaKF30HMfmF-Fw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What happens if we substitute the name for a fictional character, or if we change the capitalization of some of the words around the name? Here I've changed the name from &lt;em&gt;Alex Sharp&lt;/em&gt; to &lt;em&gt;Ronald McDonald&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Both APIs seem to have a &lt;strong&gt;much easier time&lt;/strong&gt; recognizing a Person entity if it's &lt;em&gt;not surrounded&lt;/em&gt; by other capitalized words.&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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2APTAl0_xleI70BU4rxHlAow.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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2APTAl0_xleI70BU4rxHlAow.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Amazon recognizes both forms but has a &lt;strong&gt;much&lt;/strong&gt; higher confidence level when &lt;em&gt;Ronald McDonald&lt;/em&gt; is not surrounded by a capitalized word.&lt;/p&gt;

&lt;p&gt;Google's results are more stark, &lt;strong&gt;failing to recognize a Person entity at all&lt;/strong&gt; if the term is surrounded by other capitalized nouns: it recognizes the whole phrase &lt;em&gt;Ronald McDonald Experience&lt;/em&gt; as "Other". It thinks it's something, but it doesn't know what.&lt;/p&gt;

&lt;p&gt;While these results make logical sense to a layman - capitalized words are often proper nouns - it's a bit disappointing that these products rely on such basic and fragile grammar rules.&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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AK8JppWlNptSComUDr_XipA.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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AK8JppWlNptSComUDr_XipA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2A31cOyb_Woa0IOWLWSHB5xQ.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%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2A31cOyb_Woa0IOWLWSHB5xQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ☝️Massively Unqualified Advice to Amazon &amp;amp; Google
&lt;/h2&gt;

&lt;p&gt;It seems to me (&lt;em&gt;enormous caveat&lt;/em&gt;: I'm a complete ML/AI amateur) that the person entity recognition issue could be improved by identifying names based on whether they match (or don't match) dictionary words. Neither the words &lt;em&gt;joe&lt;/em&gt; or &lt;em&gt;rogan&lt;/em&gt; are dictionary words, so can we reasonably assume, with mild confidence, that paired together, &lt;em&gt;joe rogan&lt;/em&gt; might be someone's name? I dunno, I'm way beyond swimming in the deep end of a pool I barely understand 🤷🏻‍♂️.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧙‍♀️🚫🦄 No Magic Here
&lt;/h2&gt;

&lt;p&gt;As we can see, these APIs can be &lt;strong&gt;incredibly fragile&lt;/strong&gt;, often reacting in odd and unexpected ways to tiny changes in input.&lt;/p&gt;

&lt;p&gt;They seem to operate around fairly rudimentary grammatical "rules" - proper nouns must be capitalized, proper nouns must exist on their own - which are in many cases &lt;em&gt;incredibly fragile&lt;/em&gt;, especially considering that many of us aren't exactly writing on the internet and social media in academically sanctioned grammar. Change an uppercase letter to lowercase and the whole thing breaks, and poor Joe Rogan is robbed of his personhood. Sad. 😟&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%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AKruDl3ONh8_h0c6CPpD29w.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AKruDl3ONh8_h0c6CPpD29w.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outside of this largely underwhelming but head-scratching exercise in curiosity, there is some truly &lt;a href="https://deepmind.com/blog/alphastar-mastering-real-time-strategy-game-starcraft-ii/" rel="noopener noreferrer"&gt;mind-blowing work&lt;/a&gt; happening in &lt;a href="https://medium.com/syncedreview/best-nlp-model-ever-google-bert-sets-new-standards-in-11-language-tasks-4a2a189bc155" rel="noopener noreferrer"&gt;deep learning powered&lt;/a&gt; machine learning and &lt;a href="https://pytext-pytext.readthedocs-hosted.com/en/latest/index.html" rel="noopener noreferrer"&gt;NLP&lt;/a&gt;. Unfortunately, AWS Comprehend and Google AutoML feel more like the training wheels version of a technology that can literally type words before we've thought of them, beat humans at complex strategy games, drive cars, and more. Unfortunately, these APIs are pretty underwhelming for anything other than basic grammar categorization and sentiment analysis (not covered here).&lt;/p&gt;




&lt;p&gt;&lt;em&gt;🙏 Thanks for reading. If you're interested in learning more about the product that inspired the work for this post, check out and subscribe to&lt;/em&gt; &lt;strong&gt;Follow Reset&lt;/strong&gt;, &lt;em&gt;which will soon make it very easy to clean up your Twitter feed.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>nlp</category>
      <category>ai</category>
    </item>
    <item>
      <title>React CRA + Netlify = 💯❤</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Mon, 28 Jan 2019 18:13:18 +0000</pubDate>
      <link>https://dev.to/ajsharp/react-cra--netlify---2jp</link>
      <guid>https://dev.to/ajsharp/react-cra--netlify---2jp</guid>
      <description>&lt;p&gt;I've been shipping static frontend to s3/cloudfront for a while, and I finally gave &lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt; a chance and &lt;strong&gt;wow is it easy.&lt;/strong&gt; You connect your github repo, give it a command to run and done. They handle all the cloudfront / CDN stuff behind the scenes that I used to have to configure manually.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.netlify.com/blog/2016/07/22/deploy-react-apps-in-less-than-30-seconds/"&gt;See here&lt;/a&gt; for more.&lt;/p&gt;




&lt;p&gt;☝️ &lt;em&gt;&lt;strong&gt;Be sure to check out &lt;a href="https://www.sharesecret.co"&gt;Sharesecret&lt;/a&gt;, which makes it easy to securely share sensitive data.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>todayilearned</category>
      <category>deployment</category>
      <category>workjournal</category>
    </item>
    <item>
      <title>Elasticsearch full-text queries explained, for humans 🤓</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Sat, 26 Jan 2019 01:24:21 +0000</pubDate>
      <link>https://dev.to/ajsharp/elasticsearch-full-text-queries-explained-for-humans--1kfk</link>
      <guid>https://dev.to/ajsharp/elasticsearch-full-text-queries-explained-for-humans--1kfk</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html"&gt;ElasticSearch Full-text query Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ES has different query types. A quick summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;match&lt;/code&gt; - standard full text query&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;match_phrase&lt;/code&gt; - phrase matching. like when you put a term in quotes on google.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;match_phrase_prefix&lt;/code&gt; - poor man’s autocomplete.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;multi_match&lt;/code&gt; - Multi-field &lt;code&gt;match&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;common&lt;/code&gt; (not covered here) - Takes stopwords (e.g. “the”) into account.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;query_string&lt;/code&gt; (not covered here) - Expert mode. Can use AND|OR|NOT and multi-field search in a query string.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;simple_query_string&lt;/code&gt; (not covered here) - Simpler “more robust” for exposing to end-users. (how is simple more robust? seems counter-intuitive. no one knows.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;match&lt;/code&gt; - standard full text query
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default does near-exact word equality matching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt;: If you're doing full-text search on a large text field, such as the body of this post.&lt;/p&gt;

&lt;p&gt;Good default for matching a word or phrase in a block of text, e.g. searching in a large text field, description field, etc, such as searching for a phrase in someone’s Twitter bio.&lt;/p&gt;

&lt;p&gt;Not good for partial matches of a single word or phrase, such as a partial match of someone’s Twitter username (see fuzziness below).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuzzy matching&lt;/strong&gt;&lt;br&gt;
Allows &lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#fuzziness"&gt;fuzzy matching&lt;/a&gt; (e.g. typo tolerance) by specifying a &lt;a href="http://en.wikipedia.org/wiki/Levenshtein_distance"&gt;levenstein edit distance&lt;/a&gt;, number of one character changes needed to make one string match another string. Basically, it’s the number of typos you can make and still match the string.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example&lt;/em&gt;: Your target match data is a field with the value “ajsharp”. With the &lt;code&gt;fuzziness&lt;/code&gt; param set to 1, you can type “jjsharp” and it will match “ajsharp”. But if you type “jssharp” it won’t match, unless you increase &lt;code&gt;fuzziness&lt;/code&gt; to 2.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;match_phrase&lt;/code&gt; - for matching exact phrases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; If you need to be specific about whole phrase searches, or want to enable this functionality for your users.&lt;/p&gt;

&lt;p&gt;Let’s say we have two twitter profiles indexed. Document A has the phrase “co-founder” in the bio, and Document B just has the word “founder”. &lt;/p&gt;

&lt;p&gt;If you search “founder” using match_phrase, both documents will match.&lt;br&gt;
If you search “co-founder” using match_phrase, only Document A will match. However, had you done this query using &lt;code&gt;match&lt;/code&gt;, both Document A and Document B would match the query “co-founder”&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;match_phrase_prefix&lt;/code&gt; - poor man’s autocomplete
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase-prefix.html"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt;: Only you need to match a single field. For many use-cases &lt;code&gt;multi_match&lt;/code&gt; feels &lt;em&gt;far&lt;/em&gt; more useful.&lt;/p&gt;

&lt;p&gt;From the ES docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Consider the query string quick brown f. This query works by creating a phrase query out of quick and brown (i.e. the term quick must exist and must be followed by the term brown). Then it looks at the sorted term dictionary to find the first 50 terms that begin with f, and adds these terms to the phrase query.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Can be enhanced/improved upon with &lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html"&gt;Completion Suggester&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;multi_match&lt;/code&gt; - multi-field match 🎉🎉🎉
&lt;/h2&gt;

&lt;p&gt;Allows you to search for the same string in multiple fields.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt;: In many cases this is probably what you need if you're doing anything auto-completey (note: there are probably many uses cases this is great for but my primary one when I wrote this post was autocomplete, so 🤷🏻‍♂️).&lt;/p&gt;

&lt;p&gt;Multi match queries can have a type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;best_fields&lt;/code&gt;. Default. Match any field, but uses the _score from the best field. &lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#type-best-fields"&gt;Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;most_fields&lt;/code&gt; - Matches any field and combines the score&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cross_fields&lt;/code&gt; - Treats fields with same analyzer as if one big field.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;phrase&lt;/code&gt; - Uses &lt;code&gt;match_phrase&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🎉🎉🎉 &lt;code&gt;phrase_prefix&lt;/code&gt; - Uses &lt;code&gt;match_phrase_prefix&lt;/code&gt; on each field and combines the _score. Allows multi-field autocomplete 💥💥💥&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Field Boosting&lt;/strong&gt;&lt;br&gt;
Fields can be boosted by using the &lt;code&gt;^&lt;/code&gt; followed by number. Assume twitter profiles with screen_name and name fields. If you do a query like this, the screen_name will be three times as important as the name field in the ranking:&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;query&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;multi_match&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;query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;ajsharp&lt;/span&gt;&lt;span class="err"&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;fields&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="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;screen_name&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, “name” ] 
    }
  }
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;☝️ &lt;em&gt;&lt;strong&gt;Be sure to check out &lt;a href="https://www.sharesecret.co"&gt;Sharesecret&lt;/a&gt;, which makes it easy to securely share sensitive data.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>elasticsearch</category>
      <category>notes</category>
      <category>workjournal</category>
    </item>
    <item>
      <title>🚫😩 An array of react refs</title>
      <dc:creator>Alex Sharp 🛠sharesecret.co</dc:creator>
      <pubDate>Fri, 25 Jan 2019 04:20:07 +0000</pubDate>
      <link>https://dev.to/ajsharp/-an-array-of-react-refs-pnf</link>
      <guid>https://dev.to/ajsharp/-an-array-of-react-refs-pnf</guid>
      <description>&lt;p&gt;Apparently you can't store &lt;a href="https://reactjs.org/docs/refs-and-the-dom.html"&gt;React refs&lt;/a&gt; in an array. For some reason they get wiped out, so if you need to store a collection of refs, you have to do something like this (forgive me lord, for I hath sinned):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&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;label 1&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;label 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SinFactory&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
            &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`ref&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;p&gt;It's truly filthy, but it works. &lt;/p&gt;




&lt;p&gt;☝️ &lt;em&gt;&lt;strong&gt;Be sure to check out &lt;a href="https://www.sharesecret.co"&gt;Sharesecret&lt;/a&gt;, which makes it easy to securely share sensitive data.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>react</category>
      <category>facepalm</category>
      <category>workjournal</category>
    </item>
  </channel>
</rss>
