<?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>Forem: Andy Huynh</title>
    <description>The latest articles on Forem by Andy Huynh (@andy4thehuynh).</description>
    <link>https://forem.com/andy4thehuynh</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%2F377664%2F4cfe8932-91fc-4669-859c-34f3df7f63be.png</url>
      <title>Forem: Andy Huynh</title>
      <link>https://forem.com/andy4thehuynh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andy4thehuynh"/>
    <language>en</language>
    <item>
      <title>A Brief Introduction to Sales Engineering</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Mon, 11 Dec 2023 19:51:45 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/a-brief-introduction-to-sales-engineering-h22</link>
      <guid>https://forem.com/andy4thehuynh/a-brief-introduction-to-sales-engineering-h22</guid>
      <description>&lt;p&gt;Sales Engineering is the intersection of technology and sales. It's ideal for people like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extroverted engineers&lt;/li&gt;
&lt;li&gt;Sales people who enjoy talking technology&lt;/li&gt;
&lt;li&gt;Not your grandma that doom scrolls on Facebook&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the words of Chris White, the author of The Six Habits of Highly Effective Sales Engineers&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(Sales Engineering) is simply to show them – no, CONVINCE them – that your software, solutions, and company will meet their requirements, solve their problems, and enable them to achieve their desired outcomes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What do Sales Engineers sell?
&lt;/h3&gt;

&lt;p&gt;Well that depends on the company you're working for and your level of expertise in their product. Knowledgable Sales Engineers (or SEs) can sell products ranging from AI productivity tools, endpoint security solutions to grid-scale power converters. They become subject matter experts (SME) in the product and become the go to resource as a vendor when companies are interested in integrating your product into their systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if I'm an experience software engineer?
&lt;/h3&gt;

&lt;p&gt;There are plenty of SaaS companies interested in your skillsets in application development, security and devops. Software engineers that like to talk can make a lucrative career in Sales Engineering. Companies like &lt;a href="https://snyk.io/"&gt;Snyk&lt;/a&gt;, &lt;a href="https://crowdstrike.com/"&gt;Crowdstrike&lt;/a&gt; and &lt;a href="https://automattic.com/"&gt;Automattic&lt;/a&gt; have dedicated SEs that work with customers in pre-sales (before purchase) and post-sales (after purchase) to ensure the customer journey is successful. As an engineer, if you don't want to go through yet another 2 week product sprint... if you understand software development at the application layer.. if you want to try something new... Sales Engineering might be for you!&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Engineer to Sales Engineer Journey
&lt;/h3&gt;

&lt;p&gt;Who am I? I'll be the guinea pig for current software engineers interested in seeing how this transition is accomplished. I've dedicated 9 years to multiple SaaS startups (1 unicorn) building features still in production today and earning a title I've always wanted as Senior Ruby on Rails Developer. I'm working full time to transition to the world of tech sales and will document my journey as well as provide value like where to find the best job boards, how to structure your resume and what kind of questions will be asked in SE related interviews.&lt;/p&gt;

&lt;p&gt;As of this date, I've landed a &lt;strong&gt;six-figure Sales Engineering role for a prominent E-Commerce SaaS company... and rejected it.&lt;/strong&gt; I'll explain in future posts why you might've rejected it too. &lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Sales Engineering is a viable path for software engineers looking to work in more client facing roles. It'll allow you to flex the muscle of selling the value of a product to customers and leverage your existing experience as a software engineer.&lt;/p&gt;

&lt;p&gt;I'll add to this by saying I plan to add as much value to your life as I can. I'm currently a Sales Engineering student at &lt;a href="https://www.presalesacademy.com/"&gt;PreSales Academy&lt;/a&gt; and want to share what I can to help make this transition for you smooth and enjoyable. &lt;/p&gt;

</description>
      <category>sales</category>
      <category>solutions</category>
      <category>beginners</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Integrating Astro, Netlify and Mantine</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Wed, 21 Dec 2022 22:22:23 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/astro-and-mantine-ui-4ej9</link>
      <guid>https://forem.com/andy4thehuynh/astro-and-mantine-ui-4ej9</guid>
      <description>&lt;p&gt;Warning, don't bother using this stack as of Dec 21, 2022. &lt;/p&gt;

&lt;p&gt;In the spirit of cultivating more empathy in my life, I'm recreating my sister's virtual kitchen website using Astro for blazingly fast response times, Mantine UI for out-of-the-box components and Netlify for ease of distribution.&lt;/p&gt;

&lt;p&gt;The steps from nothing to all components viewable in production should've been simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new Astro project using Netlify's template wizard&lt;/li&gt;
&lt;li&gt;Pull that repo down from Github and &lt;code&gt;npm install&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Follow instructions to install React on Astro's website and Mantine from their documentation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What started as a terrible first experience using Astro with a component library like Mantine, turned into a wild goose chase if they're compatible.&lt;/p&gt;

&lt;p&gt;After stumbling upon &lt;a href="https://stackoverflow.com/questions/73941829/how-to-integrate-mui-in-react-integrated-astro-site" rel="noopener noreferrer"&gt;this Stackoverflow issue&lt;/a&gt; and &lt;a href="https://github.com/withastro/astro/issues/4432" rel="noopener noreferrer"&gt;this Github Issue&lt;/a&gt;, it's concluded that Astro does not support CSS-in-Javascript for their component styling. BOO!&lt;/p&gt;

</description>
      <category>interview</category>
      <category>analytics</category>
    </item>
    <item>
      <title>LoadError: cannot load such file -- aws-sdk-core/plugins/http_checksum.rb</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Fri, 12 Jun 2020 18:01:02 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/loaderror-cannot-load-such-file-aws-sdk-core-plugins-httpchecksum-rb-4ljc</link>
      <guid>https://forem.com/andy4thehuynh/loaderror-cannot-load-such-file-aws-sdk-core-plugins-httpchecksum-rb-4ljc</guid>
      <description>&lt;p&gt;AWS Comprehend is in its early stages. The dev world is slowly seeing its potential. It's a struggle getting it set up with your Rails environment. The following resolved my problems. I hope it solves yours, too!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/clients/aws_comprehend.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Clients::AwsComprehend&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
    &lt;span class="no"&gt;Aws&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Comprehend&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;region: &lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"AWS_REGION"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="ss"&gt;access_key_id: &lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"AWS_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="ss"&gt;secret_access_key: &lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"AWS_SECRET_ACCESS_KEY"&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;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight irb"&gt;&lt;code&gt;&lt;span class="go"&gt;&amp;gt; Clients::AwsComprehend.()
&lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;NameError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uninitialized&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="no"&gt;Aws&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Comprehend&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="n"&gt;such&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;http_checksum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="no"&gt;LoadError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="n"&gt;such&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;http_checksum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;After digging online, this Github issue comment did the trick: &lt;a href="https://github.com/aws/aws-sdk-ruby/issues/1872#issuecomment-461634704"&gt;https://github.com/aws/aws-sdk-ruby/issues/1872#issuecomment-461634704&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight irb"&gt;&lt;code&gt;&lt;span class="go"&gt;&amp;gt; bundle update aws-sdk-s3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight irb"&gt;&lt;code&gt;&lt;span class="go"&gt;&amp;gt; Clients::AwsComprehend.()
&lt;/span&gt;&lt;span class="p"&gt;=&amp;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="ow"&gt;not&lt;/span&gt; &lt;span class="ss"&gt;found: &lt;/span&gt;&lt;span class="s2"&gt;"AWS_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously this is returns a different problem. However, updating &lt;code&gt;aws-sdk-core&lt;/code&gt; to the latest will get you past the load error. &lt;/p&gt;

</description>
      <category>ruby</category>
      <category>aws</category>
    </item>
    <item>
      <title>Vim tip - remap CAPS LOCK to control</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Thu, 04 Jun 2020 16:57:05 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/vim-tip-remap-caps-lock-to-control-3ih8</link>
      <guid>https://forem.com/andy4thehuynh/vim-tip-remap-caps-lock-to-control-3ih8</guid>
      <description>&lt;h4&gt;
  
  
  Before
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MJW_weM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/A6Q4tQM.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MJW_weM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/A6Q4tQM.jpg" alt="Default control mapping" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  After
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bIsl3RH5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cZh71Rc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bIsl3RH5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cZh71Rc.jpg" alt="Modded to caps lock" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If carpel tunnel is a real fear, remapping &lt;code&gt;control&lt;/code&gt; key will assuage your troubles.&lt;/p&gt;

&lt;p&gt;Many Vim packages rely on &lt;code&gt;control&lt;/code&gt; to unlock their Vim toolset. Tmux uses it (in conjunction with the literal letter 'b') to move to different panes (tmux). This is the primary reason for this post.&lt;/p&gt;

&lt;p&gt;Ergonomically &lt;code&gt;control&lt;/code&gt; is in a shitty spot on standard keyboard layouts. Reaching for &lt;code&gt;control&lt;/code&gt;, over time, garners pain in your hands quicker than you think. I've used Vim for the past five years with no finger pain. I include instructions to remap CAPS LOCK below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Open system preferences&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oeKMM2h2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/ykMNEHY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oeKMM2h2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/ykMNEHY.png" alt="Go to system preferences" width="724" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Find and click the keyboard icon&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F_c7yrBU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/SBOa6gG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F_c7yrBU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/SBOa6gG.png" alt="mac keyboard section" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Click modifier keys&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GIGKLm5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Y9ChpRJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GIGKLm5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Y9ChpRJ.png" alt="mac modifier keys" width="800" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Set caps lock to control&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vqlm95pb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/6irVHPV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vqlm95pb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/6irVHPV.png" alt="caps lock to control" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. (Optional) Set &lt;code&gt;CTRL-b&lt;/code&gt; to &lt;code&gt;CTRL-a&lt;/code&gt; in &lt;code&gt;.tmux.conf&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Ctrl-b sucks. lets bind ctrl-a instead
unbind C-b
set -g prefix C-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The literal letter 'a' is closer to CAPS LOCK than 'b'.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vim</category>
      <category>beginners</category>
    </item>
    <item>
      <title>testing Apple Pay on the web with Stripe (Rails)</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Fri, 29 May 2020 23:15:52 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/testing-apple-pay-on-the-web-with-stripe-rails-3f1k</link>
      <guid>https://forem.com/andy4thehuynh/testing-apple-pay-on-the-web-with-stripe-rails-3f1k</guid>
      <description>&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%2Fi.imgur.com%2FCZv5lQF.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%2Fi.imgur.com%2FCZv5lQF.png" alt="Proof"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stripe.com/docs/stripe-js/elements/payment-request-button#html-js-prerequisites" rel="noopener noreferrer"&gt;Following this guide to render an Apply Pay button with Stripe.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stripe provided a fantastic tutorial to integrate Apple Pay with Stripe. It took me half a day to render a button on the page. Here are the fine details of the guide I overlooked to eventually succeed in rendering Apple Pay.&lt;/p&gt;

&lt;p&gt;1)  &lt;strong&gt;Ensure a credit card exists in your Chrome browser wallet&lt;/strong&gt;. I had Google Pay in my wallet. It was oddly frustrating, and understandable, Apple Pay didn't recognize Google Pay. Anyways, use a CC&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%2Fi.imgur.com%2FNMvT4NH.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%2Fi.imgur.com%2FNMvT4NH.png" alt="Credit card"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2)  &lt;strong&gt;Enable HTTPS with ngrok&lt;/strong&gt;. I'm on &lt;code&gt;ngrok version 2.2.4&lt;/code&gt;. Adjust your domain port accordingly&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ngrok http &lt;span class="nt"&gt;-host-header&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rewrite localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3)  &lt;strong&gt;Render text from the controller, explicitly&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In `config/routes.rb` point the weirdly dotted namespaced controller endpoint to `ApplePayController` &lt;/span&gt;
&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;".well-known/apple-developer-merchantid-domain-association"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"apple_pay#show"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# `app/controllers/apple_pay_controller.rb` render text&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplePayController&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;show&lt;/span&gt;
    &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&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="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="no"&gt;DomainAssociationFile&lt;/span&gt;&lt;span class="o"&gt;.&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;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I initially served html from the controller. I saw text rendered in the web browser.&lt;/p&gt;

&lt;p&gt;When registering my domain with Apple, I got 500 errors.&lt;/p&gt;

&lt;p&gt;Apple pinged my controller to retrieve the domain association file. It didn't know how to respond to the HTML I gave back. Stripe expected a text format in the return response. Format it like the above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# I threw this in a presenter&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DomainAssociationFile&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;FILE&lt;/span&gt;&lt;span class="sh"&gt;
      # download and paste your domain association file, here
&lt;/span&gt;&lt;span class="no"&gt;    FILE&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;



</description>
      <category>rails</category>
      <category>stripe</category>
      <category>apple</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>handy Ruby methods #4 - Hash#dig</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Thu, 28 May 2020 16:05:30 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/handy-ruby-methods-4-hash-dig-3ga5</link>
      <guid>https://forem.com/andy4thehuynh/handy-ruby-methods-4-hash-dig-3ga5</guid>
      <description>&lt;p&gt;&lt;a href="https://i.giphy.com/media/Dbp2zw1MjeK5i/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Dbp2zw1MjeK5i/giphy.gif" alt="cool diglet" width="500" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Before Ruby 2.3
&lt;/h5&gt;



&lt;div class="highlight js-code-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;AutomationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;automation_trigger_type&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:automation_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:trigger_attributes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;trigger_type&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"unknown type"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;trigger_type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&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;h5&gt;
  
  
  After Ruby 2.3
&lt;/h5&gt;



&lt;div class="highlight js-code-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;AutomationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;automation_trigger_type&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:automation_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:trigger_attributes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;trigger_type&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"unknown type"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;trigger_type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&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;Life after Ruby 2.3 breathes an elegant expression to drill into a hash.&lt;/p&gt;

&lt;p&gt;In the first example, &lt;code&gt;Hash#fetch&lt;/code&gt; is invoked multiple times. It drills two levels into a nested params hash &lt;code&gt;:automation_rule&lt;/code&gt;. A default is included to avoid the dreaded &lt;code&gt;NoMethodErrors on nil&lt;/code&gt; error. &lt;/p&gt;

&lt;p&gt;This approach is verbose to say the least. It's painful to look at in the eyes of a Ruby dev.&lt;/p&gt;

&lt;p&gt;The latter example is more terse. First, &lt;code&gt;Hash#dig&lt;/code&gt; checks if the param key &lt;code&gt;:automation_rule&lt;/code&gt; exists. If there's a key, it digs down a nested level and looks for the key &lt;code&gt;:trigger_attributes&lt;/code&gt;. And so on..&lt;/p&gt;

&lt;p&gt;Anywhere &lt;code&gt;Hash#dig&lt;/code&gt; does not find a key, it returns nil in lieu of an error.&lt;/p&gt;

&lt;p&gt;I notice &lt;code&gt;Hash#dig&lt;/code&gt; used in Rails controllers. Digging into controller params is commonplace as an app builds in complexity. It's also prevalent digging through an API response where the returned payload is a deeply nested JSON object.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Hash#dig&lt;/code&gt; is a staple to write battle-tested code.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>beginners</category>
    </item>
    <item>
      <title>my personal checklist deploying to Heroku</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Tue, 26 May 2020 01:20:31 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/my-personal-checklist-deploying-to-heroku-4ih3</link>
      <guid>https://forem.com/andy4thehuynh/my-personal-checklist-deploying-to-heroku-4ih3</guid>
      <description>&lt;p&gt;This post serves as my single source of truth deploying local changes to a Heroku app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/CDZwopbecAbIc/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/CDZwopbecAbIc/giphy.gif" alt="deploy the app" width="706" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Local(production) to Github(production)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Pull the latest changes from master &lt;code&gt;git pull origin master&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Switch to production branch. Update that shit &lt;code&gt;git checkout production&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Look over diffs for both master/production branches. It's more or less a sanity check &lt;code&gt;git diff production..master&lt;/code&gt;. Take notes of features you're merging&lt;/li&gt;
&lt;li&gt;Looks good? Merge changes from master to production on your production branch &lt;code&gt;git merge master&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Push the latest version production to Github &lt;code&gt;git push origin production&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  Github(production) to Heroku Staging
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Check Heroku for green status: &lt;code&gt;heroku status&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Push to production:master branch on staging, update the schema (if needed) and reboot the app &lt;code&gt;git push staging production:master &amp;amp;&amp;amp; heroku run rake db:migrate -r staging &amp;amp;&amp;amp; heroku restart -r staging&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Wait for the dyno slug to change &lt;code&gt;watch -n 5 bin/deploy_slug_information&lt;/code&gt; &lt;em&gt;(details below on this script)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Login to staging. Poke around features you just merged&lt;/li&gt;
&lt;li&gt;Check JS console for any interesting front end errors&lt;/li&gt;
&lt;li&gt;Check &lt;a href="https://honeybadger.io/"&gt;Honeybadger&lt;/a&gt; for server errors&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  Github(production) to Heroku Production
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Push to production:master branch on staging, update the schema (if needed) and reboot the app  &lt;code&gt;git push production production:master &amp;amp;&amp;amp; heroku run rake db:migrate -r production &amp;amp;&amp;amp; heroku restart -r production&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ensure latest SHA release is the same as production branch &lt;code&gt;heroku releases -r production | grep &amp;lt;production_SHA&amp;gt;&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Check HoneyBadger for errors from release&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;How to run &lt;code&gt;watch -n 5 bin/deploy_slug_information&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  Setup an executable in your bin directory to watch &lt;code&gt;./bin/deploy_slug_information&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://my-app-name.com"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"staging"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://my-app-name-staging.com"&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;URL+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/deploy_slug_information.json"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$URL&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$URL&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Add middleware to your Rails app &lt;code&gt;app/middleware/deploy_slug_information.rb&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-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;DeploySlugInformationMiddleware&lt;/span&gt;
  &lt;span class="no"&gt;HEADER&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"X-Slug-Commit"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;
  &lt;span class="no"&gt;JSON_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/deploy_slug_information.json"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@app&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
    &lt;span class="vi"&gt;@partial_sha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HEROKU_SLUG_COMMIT"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;presence&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&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;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"PATH_INFO"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;JSON_ENDPOINT&lt;/span&gt;
      &lt;span class="n"&gt;json_endpoint_reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;header_injection_reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&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="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;header_injection_reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;HEADER&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@partial_sha&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;json_endpoint_reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;slug_commit: &lt;/span&gt;&lt;span class="vi"&gt;@partial_sha&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;

    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"Content-Length"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&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="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Unix trick -  use &lt;code&gt;fc&lt;/code&gt; to edit and execute your most recently used shell command.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>heroku</category>
      <category>beginners</category>
    </item>
    <item>
      <title>mutating objects in Ruby</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Thu, 21 May 2020 19:55:12 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/mutating-objects-in-ruby-2hp9</link>
      <guid>https://forem.com/andy4thehuynh/mutating-objects-in-ruby-2hp9</guid>
      <description>&lt;p&gt;&lt;a href="https://i.giphy.com/media/1ZbnufnHeW0W4/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/1ZbnufnHeW0W4/giphy.gif" alt="teenage mutant ninja turtles" width="500" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mutation bugs are some of the most common in Rubyland. &lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Variables are objects and they most likely contain data. This means one or more variables may read data from that variable. If we change the makeup of the object, it could spell disaster for other objects expecting it not to change.&lt;/p&gt;

&lt;p&gt;This is prevalent when passing objects via method calls. If a method param gets mutated and passed to another method, the receiving method might not respond properly to the mutated data. The results are less malleable and unreliable code. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One reason to mutate an object is if you're crafting data.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;ApplicationHelper&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;admin_body_classes&lt;/span&gt;
    &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"admin"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;admin?&lt;/span&gt;
    &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:controller&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"environment"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test?&lt;/span&gt;

    &lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@extra_body_classes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@extra_body_classes&lt;/span&gt;
    &lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&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="nf"&gt;tr&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="s2"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, mutation makes sense. We're returning a data object at the end of &lt;code&gt;admin_body_classes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It would not make sense to use a non-mutating operand to &lt;code&gt;classes&lt;/code&gt;. &lt;code&gt;Array#concat&lt;/code&gt; or a shovel operand are suitable for this case since &lt;code&gt;classes&lt;/code&gt; is being mutated throughout the method. &lt;/p&gt;

&lt;p&gt;Being mindful of object mutation saves headaches when dealing with objects.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>beginners</category>
    </item>
    <item>
      <title>create a shortcut to toggle paste mode with Vim</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Tue, 19 May 2020 14:50:38 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/create-a-shortcut-to-toggle-paste-mode-with-vim-5205</link>
      <guid>https://forem.com/andy4thehuynh/create-a-shortcut-to-toggle-paste-mode-with-vim-5205</guid>
      <description>&lt;p&gt;&lt;a href="https://i.giphy.com/media/3oKIPnAiaMCws8nOsE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3oKIPnAiaMCws8nOsE/giphy.gif" alt="copy cat" width="360" height="378"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Vim has a paste mode you can toggle on or off - &lt;code&gt;:set paste&lt;/code&gt; and &lt;code&gt;:set nopaste&lt;/code&gt;. What if you can do this with less keystrokes?&lt;/p&gt;

&lt;p&gt;Essentially, these commands prevent weird formatting when pasting text into your editor.&lt;/p&gt;

&lt;p&gt;I will say - copy/pasting isn't a trivial action. Expect to perform copy/paste tenfold throughout your career. Typing out these commands gets cumbersome. If only we can shortcut this to improve your workflow.&lt;/p&gt;

&lt;p&gt;Below is a &lt;a href="https://stackoverflow.com/questions/1764263/what-is-the-leader-in-a-vimrc-file"&gt;leader command&lt;/a&gt; to which you can add to&lt;code&gt;.vimrc&lt;/code&gt; (config file). Leader commands are merely a fancy shortcut native to Vim.&lt;/p&gt;

&lt;h4&gt;
  
  
  .vimrc
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; TogglePaste&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&amp;amp;&lt;span class="nb"&gt;paste&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;set&lt;/span&gt; &lt;span class="nb"&gt;paste&lt;/span&gt;
        echo &lt;span class="s2"&gt;"Paste Mode Enabled"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;nopaste&lt;/span&gt;
        echo &lt;span class="s2"&gt;"Paste Mode Disabled"&lt;/span&gt;
    &lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;p&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; TogglePaste&lt;span class="p"&gt;()&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Vimscript knowledge necessary. Just "copy/paste" this snippet to your &lt;code&gt;.vimrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ensure your terminal shell of choice knows about your updates. I either restart my terminal session or &lt;a href="https://stackoverflow.com/questions/803464/how-do-i-source-something-in-my-vimrc-file"&gt;source my &lt;code&gt;.vimrc&lt;/code&gt;.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toggle on paste mode:&lt;/strong&gt; hit the key combination &lt;code&gt;\&lt;/code&gt; + &lt;code&gt;p&lt;/code&gt;. If this doesn't work... ensure you're in Vim normal mode (not insert or visual).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toggle off paste mode:&lt;/strong&gt;  &lt;code&gt;\&lt;/code&gt; + &lt;code&gt;P&lt;/code&gt;. &lt;/p&gt;

</description>
      <category>vim</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>handy Ruby methods #3 - Hash#fetch</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Sun, 17 May 2020 15:53:06 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/handy-ruby-methods-3-hash-fetch-2adm</link>
      <guid>https://forem.com/andy4thehuynh/handy-ruby-methods-3-hash-fetch-2adm</guid>
      <description>&lt;div class="highlight js-code-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;StripePaymentIntegration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enabled?&lt;/span&gt;
    &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ENABLE_STRIPE_PAYMENT_INTEGRATION"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code isn't bulletproof. If it's not obvious - let me help you.&lt;/p&gt;

&lt;p&gt;This is disabled by default. When we push to production, the app reboots.  There exists a small window where &lt;code&gt;ENABLE_STRIPE_PAYMENT_INTEGRATION&lt;/code&gt; isn't set. The code &lt;em&gt;technically&lt;/em&gt; isn't doing what you're expecting. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why does the app reboot? Because Heroku dynos automatically restart with every new code release. &lt;a href="https://www.heroku.com/dynos/lifecycle"&gt;Here's a short description of Heroku dynos.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If only we can set a default value to avoid to ensure this is enabled when we push. It'd be even better if it was in pure Ruby.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;StripePaymentIntegration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enabled?&lt;/span&gt;
    &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ENABLE_STRIPE_PAYMENT_INTEGRATION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! Understand that &lt;code&gt;ENV&lt;/code&gt; serves as a &lt;em&gt;hash-like structure&lt;/em&gt;. Thus, it can "fetch" a hash's value given a key. &lt;code&gt;Hash#fetch&lt;/code&gt; takes a lookup key in the first parameter and an optional second as a fallback value.&lt;/p&gt;

&lt;p&gt;You can deploy and now be sure this works correctly!&lt;/p&gt;

&lt;p&gt;I believe you get the most out of a software language by writing it as it's meant to be written. One of the pillars writing good Ruby code is being expressive. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;ENV.fetch("ENABLE_STRIPE_PAYMENT_INTEGRATION", "true")&lt;/code&gt; comment below if that doesn't express what I'm puttin' down.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>heroku</category>
    </item>
    <item>
      <title>the difference between RSpec eq and be</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Fri, 15 May 2020 16:03:45 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/the-difference-between-rspec-eq-and-be-3jep</link>
      <guid>https://forem.com/andy4thehuynh/the-difference-between-rspec-eq-and-be-3jep</guid>
      <description>&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%2Fmiro.medium.com%2Fmax%2F800%2F1%2APr8GffnQMojxKwRqCRsGZw.gif" 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%2Fmiro.medium.com%2Fmax%2F800%2F1%2APr8GffnQMojxKwRqCRsGZw.gif" alt="ruby"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RSpec has two equality matchers: &lt;code&gt;eq&lt;/code&gt; and &lt;code&gt;be&lt;/code&gt;. Depending on the circumstances, &lt;code&gt;eq&lt;/code&gt; works &lt;em&gt;most of the time&lt;/em&gt;. The difference between the two is subtle. The result of understanding the difference will yield clearer and more reliable specs.&lt;/p&gt;

&lt;p&gt;Take this contrived example which expects a user name to &lt;strong&gt;be&lt;/strong&gt; "Jon".&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"#name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Fabricate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"Jon"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;scenario&lt;/span&gt; &lt;span class="s2"&gt;"User's name is Jon"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jon"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Running this test we get a failure.&lt;/p&gt;

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

Failures:

  1) User's name is Jon
     Failure/Error: expect(user.name).to be "Jon"

       expected #&amp;lt;String:70298288643660&amp;gt; =&amp;gt; "Jon"
            got #&amp;lt;String:70298288643700&amp;gt; =&amp;gt; "Jon"
...
...


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

&lt;/div&gt;

&lt;p&gt;It's failing and rightfully so! RSpec's &lt;code&gt;be&lt;/code&gt; matcher expects both entities to &lt;strong&gt;be the same object&lt;/strong&gt;. In other words, &lt;code&gt;user.name&lt;/code&gt; and the string &lt;code&gt;"Jon"&lt;/code&gt; are expected to have the same &lt;strong&gt;object_id&lt;/strong&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  irb
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Jon"&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Jon"&lt;/span&gt; 
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;002&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Jon"&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Jon"&lt;/span&gt; 
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;003&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jon&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"Jon"&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;004&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jon"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;005&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object_id&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;70185646150880&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;005&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Jon"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object_id&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;70185646097920&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Notice the object ids are different. Under the hood, RSpec is calling &lt;code&gt;Object#equal?&lt;/code&gt; which is a check at the object level. &lt;/p&gt;

&lt;p&gt;RSpec's &lt;code&gt;eq&lt;/code&gt;, is what you expect the string &lt;strong&gt;value to be matched against&lt;/strong&gt;. Going back to our earlier example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"#name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Fabricate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"Jon"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;scenario&lt;/span&gt; &lt;span class="s2"&gt;"User's name is Jon"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jon"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;After you run your spec, you're passing!&lt;/p&gt;

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

Finished in 1.12 seconds (files took 13.85 seconds to load)
1 example, 0 failures

Randomized with seed 4227
...
...


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

&lt;/div&gt;

&lt;p&gt;The user's name value is "jon". That's the same as the value of the string "Jon". Peaking under the hood again.. RSpec &lt;code&gt;eq&lt;/code&gt; invokes &lt;code&gt;===&lt;/code&gt; on the two objects which checks the return value. &lt;/p&gt;

&lt;h4&gt;
  
  
  TLDR
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;eq&lt;/code&gt; checks if the object values are the same&lt;/p&gt;

&lt;p&gt;&lt;code&gt;be&lt;/code&gt; checks if the objects are the same&lt;/p&gt;

&lt;p&gt;&lt;a href="https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers" rel="noopener noreferrer"&gt;Read more, here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>ruby</category>
      <category>rails</category>
      <category>beginners</category>
    </item>
    <item>
      <title>wtf is a feature flag?</title>
      <dc:creator>Andy Huynh</dc:creator>
      <pubDate>Thu, 14 May 2020 18:31:24 +0000</pubDate>
      <link>https://forem.com/andy4thehuynh/wtf-is-a-feature-flag-1625</link>
      <guid>https://forem.com/andy4thehuynh/wtf-is-a-feature-flag-1625</guid>
      <description>&lt;p&gt;&lt;a href="https://i.giphy.com/media/7ieIikuzaJ67qNlYhz/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/7ieIikuzaJ67qNlYhz/giphy.gif" alt="bulldozer" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rollout.io/"&gt;rollout.io&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.optimizely.com/rollouts-signup"&gt;optimizely.com&lt;/a&gt;&lt;br&gt;
&lt;a href="https://launchdarkly.com/features/feature-flags"&gt;launchdarkly&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above services are bulldozers for many applications. Large companies rely on their added features like shiny dashboards and sugar methods.&lt;/p&gt;
&lt;h4&gt;
  
  
  Andy's dictionary:
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Feature flag&lt;/strong&gt;: allows your system to &lt;em&gt;conditionally show&lt;/em&gt; a feature to a customer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Feature flags are an abstraction on top of your basic programming conditionals. They house the logic of your underlying features a customer should or should not be able to access.&lt;/p&gt;

&lt;p&gt;Imagine a scenario where you're wrapping up a feature for your SaSS. It's ready to go, however - you'd be more confident if a few customers can test it out.&lt;/p&gt;

&lt;p&gt;More or less... beta testing.&lt;/p&gt;

&lt;p&gt;The above services can prove to be hefty for smaller projects. You might not have many users yet. Your codebase might not be the size of an enterprise. Did I mention those services are mostly bulldozers? Where the shovel at?&lt;/p&gt;

&lt;p&gt;I got your shovel. Integrating feature flags to Ruby projects can be accomplished using &lt;a href="https://github.com/fetlife/rollout"&gt;Rollout&lt;/a&gt;. It's minimal in it's approach and reads well. It doesn't hurt that the project has few outstanding Github issues in it's queue.&lt;/p&gt;

&lt;p&gt;Rollout also scales well. &lt;a href="//kajabi.com"&gt;Kajabi&lt;/a&gt; has a generous user base. We're releasing features non stop! We've built features on top of Rollout for our needs and it's still in use, today.&lt;/p&gt;

&lt;p&gt;Back to our contrived example, let's say you're adding an affiliate program. You have a founders group and want to ensure they get their hands on it, first! &lt;/p&gt;

&lt;p&gt;After installing the gem, define/activate your group and use conditionally write your markup like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/initializers.rb&lt;/span&gt;
&lt;span class="vg"&gt;$rollout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:founders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plan_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"founder"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="vg"&gt;$rollout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;activate_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:affiliate_program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:founders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;rollout.active&lt;/span&gt;&lt;span class="err"&gt;?(&lt;/span&gt;&lt;span class="na"&gt;:affiliate_program&lt;/span&gt;&lt;span class="err"&gt;)&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;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;affiliate_program&lt;/span&gt;&lt;span class="err"&gt;"&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;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;else&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;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;something_else&lt;/span&gt;&lt;span class="err"&gt;"&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;&lt;/span&gt;&lt;span class="err"&gt;%&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;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ruby</category>
      <category>beginners</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
