<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[darrinholst.com]]></title>
  <link href="https://darrinholst.com/rss" rel="self"/>
  <link href="https://darrinholst.com/"/>
  <updated>2023-08-26T23:45:57+00:00</updated>
  <id>https://darrinholst.com/</id>
  <author>
    <name><![CDATA[Darrin Holst]]></name>
    <email><![CDATA[darrinholst@gmail.com]]></email>
  </author>

  
  <entry>
    
      <title type="html"><![CDATA[git upall]]></title>
      <link href="https://darrinholst.com/blog/2023/02/12/git-upall/"/>
    

    
    <updated>2023-02-12T00:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2023/02/12/git-upall</id>
    <content type="html"><![CDATA[<p>I’ve had this git alias called <code class="language-plaintext highlighter-rouge">upall</code> for a while now. It finds all git
repositories and runs a <code class="language-plaintext highlighter-rouge">git up</code> on them. <code class="language-plaintext highlighter-rouge">up</code> is another alias which is
a git pull with rebase, pruning, and merged branch cleanup.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cleanup = !git fetch -p &amp;&amp; git for-each-ref --format '%(refname:short) %(upstream:track)' | awk '$2 == \"[gone]\" {print $1}' | xargs -r git branch -D
up = !git pull --rebase --prune &amp;&amp; git cleanup
upall = !"find . -type d -name .git -exec echo \\; -execdir pwd \\; -execdir git co -q main \\; -execdir bash -c \"git up | awk '/Already up/{next} {print}'\" \\;"
</code></pre></div></div>

<p>It worked fine and did what it was supposed to, but you may be able to guess the
issue that bugged me from the beginning. It was fine at first, but we must 
be getting our repositories wet because they multiply like crazy.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ /usr/bin/time git upall
      150.53 real         9.55 user         9.31 sys
</code></pre></div></div>

<p>So my goal this weekend was to wave whatever rubber chicken I needed to in
order to add some parallelism to that alias. I’ve tried and failed a couple of times 
to do this. With that in the back of my mind, I stalled and went to stack overflow to 
see what they had to say about it.</p>

<p>I found <a href="https://stackoverflow.com/questions/816619/managing-many-git-repositories">Managing many git
repositories</a>.
Asked nearly <em>14 years ago</em>. Oh boy, what kind of ancient tooling do we have in
here? There were a lot of different suggestions, but I found one comment
that was only a couple of years old promoting <a href="https://github.com/nosarthur/gita">gita</a>.
Off to github fully expecting the last commit to be a couple of years ago, but
much to my surprise it was 2 weeks ago. Bingo.</p>

<p>I blindly went back to the terminal…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ brew install gita
Warning: No available formula with the name "gita". Did you mean git, gitg or giza?
</code></pre></div></div>

<p>A few seconds of blank stares making sure I didn’t misspell it. It is only 4
letters, but ya never know. Back to the readme and a search for ‘installation’</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip3 install -U gita
</code></pre></div></div>

<p><em>Very audible sigh</em></p>

<p>I closed my eyes and followed along and was glad I did because it did exactly
what I was needing.</p>

<p>It does require you to add a repository to its known list of repositories, but it has
a <code class="language-plaintext highlighter-rouge">gita add -a</code> which will add all the repositories it finds under the current
directory.</p>

<p>The <code class="language-plaintext highlighter-rouge">super</code> command was what I was looking for which will run a git command or
alias against all of it’s managed repositories.</p>

<p>So I changed my alias to</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>upall = !"gita add -a . &amp;&amp; gita super up"
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ /usr/bin/time git upall
        3.65 real         4.70 user         5.19 sys
</code></pre></div></div>

<p>Give it a try if you have a bunch of repositories that you manage and want to
supercharge your workflow.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[JavaScript object keys ordering]]></title>
      <link href="https://darrinholst.com/blog/2021/09/25/object-keys/"/>
    

    
    <updated>2021-09-25T07:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2021/09/25/object-keys</id>
    <content type="html"><![CDATA[<p>I remember hearing about how ES6 defined made object key order a part of the
spec several years ago. Maybe from <a href="https://2ality.com/2015/10/property-traversal-order-es6.html">this article</a>.
I didn’t give it a lot of thought, because why would you ever rely
on order of keys in an object? Why not use a different data structure?
Well…because. Don’t judge me.</p>

<p>So here’s what we’re talking about. The keys from a function like <code class="language-plaintext highlighter-rouge">Object.keys</code>
return them in the same order as they were added.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">({</span>
  <span class="dl">'</span><span class="s1">foo</span><span class="dl">'</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">bar</span><span class="dl">'</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">baz</span><span class="dl">'</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="p">}).</span><span class="nx">map</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">);</span>

<span class="c1">// [ '"foo"', '"bar"', '"baz"' ]</span>
</code></pre></div></div>

<p>So far, so good. That’s about as far as my knowledge of it went. If I would have
continued to read that article or the spec I would have found out about the
actual rules, and more specifically, about integer keys. The rules are…</p>

<ol>
  <li>First, the keys that are integer indices, in ascending numeric order.</li>
  <li>Then, all other string keys, in the order in which they were added to the object.</li>
  <li>Lastly, all symbol keys, in the order in which they were added to the object.</li>
</ol>

<p>Let’s see that in action. Note that integer key means a <code class="language-plaintext highlighter-rouge">Number</code>
integer <em>or</em> a <code class="language-plaintext highlighter-rouge">String</code> integer and keys are always returned as <code class="language-plaintext highlighter-rouge">String</code>s.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">({</span>
  <span class="mi">3</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
  <span class="mi">2</span><span class="p">:</span> <span class="kc">null</span>
<span class="p">}).</span><span class="nx">map</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">);</span>

<span class="c1">// [ '"1"', '"2"', '"3"' ]</span>
</code></pre></div></div>

<p>We’re passing <code class="language-plaintext highlighter-rouge">3, '1', 2</code> in and getting <code class="language-plaintext highlighter-rouge">"1", "2", "3"</code> out.</p>

<p>Rule number 1 is where I recently got bit by this. My task was to take a group
of numbers and group them into the range defined by the keys of an object…i.e.
make a bar chart.</p>

<p>Normally that object would like…</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">({</span>
  <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">green</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">2</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">red</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">3</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">blue</span><span class="dl">'</span><span class="p">,</span>
<span class="p">});</span>

<span class="c1">// [ '1', '2', '3' ]</span>
</code></pre></div></div>

<p>So I would get the keys from this object, loop through them placing the
data points in the right bucket. The implementation of that isn’t important,
just note that it relied on the keys being in numerical order.</p>

<p>They could also be decimal numbers like…</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">({</span>
  <span class="dl">'</span><span class="s1">1.5</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">green</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">2.2</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">red</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">3.9</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">blue</span><span class="dl">'</span><span class="p">,</span>
<span class="p">});</span>

<span class="c1">// [ '1.5', '2.2', '3.9' ]</span>
</code></pre></div></div>

<p>That also worked because the source data that the object was being built from
was already sorted.</p>

<p>Can you guess where the bug is introduced?</p>

<p>Answer: mixed integers and decimals…</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">({</span>
  <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">green</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">2.2</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">red</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">3</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">blue</span><span class="dl">'</span><span class="p">,</span>
<span class="p">});</span>

<span class="c1">// [ '1', '3', '2.2' ]</span>
</code></pre></div></div>

<figure>
  <a href="https://sadtrombone.com/"><img src="/images/sadtrombone.png" /></a>
  <figcaption>&nbsp;</figcaption>
</figure>

<p>Funny how the computers always do what they were told to do. The 🔨 was to
explicitly sort the keys before using them to group the data points.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">({</span>
  <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">green</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">2.2</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">red</span><span class="dl">'</span><span class="p">,</span>
  <span class="dl">'</span><span class="s1">3</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">blue</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}).</span><span class="nx">sort</span><span class="p">((</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="o">-</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">b</span><span class="p">));</span>

<span class="c1">// [ '1', '2.2', '3' ]</span>
</code></pre></div></div>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[git squashemall]]></title>
      <link href="https://darrinholst.com/blog/2021/06/22/git-squashemall/"/>
    

    
    <updated>2021-06-22T12:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2021/06/22/git-squashemall</id>
    <content type="html"><![CDATA[<p>Sometimes through a series of unfortunate events you find yourself in a git branch hell of merge conflicts and duplicate commits. Usually it’s from a combination of a long running branch, rebasing, and merging. Your changes are small, but it seems you keep needing to resolve the same conflicts over and over again. If you’re willing to give up your prior commits and squash them all then <code class="language-plaintext highlighter-rouge">git squashemall</code> is one way to climb out of your mess.</p>

<p>Add the following to your ~/.gitconfig</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[alias]
  squashemall = !git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))
</code></pre></div></div>

<p>After running that hopefully you’re left with just your changes that you can then add, commit, and force push.</p>

<p>Details of what is going on with this command are <a href="https://stackoverflow.com/questions/25356810/git-how-to-squash-all-commits-on-branch">here</a>.</p>

<p>Remember that long running branches almost always end up bad. Avoid them at all costs.</p>
]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[The Visible Experiment]]></title>
      <link href="https://darrinholst.com/blog/2019/11/16/the-visible-experiment/"/>
    

    
    <updated>2019-11-16T12:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2019/11/16/the-visible-experiment</id>
    <content type="html"><![CDATA[<p>My asshole friends won’t join my <a href="https://www.visible.com/party-pay">visible party</a> until I write a blurgh post
describing how awesome of service it is and why they should jump off the Verizon 🚢 and on to the new Visible 🔥ness.</p>

<p>So here it is.</p>

<p>Except that’s not really how the story went.</p>

<p>I first learned of Visible a few months ago in the same way I learn about every great, new service…through podcast ads.
At the time it was a $40 flat fee for unlimited everything on Verizon’s network. Being a Verizon customer already that
sounded pretty great since I was paying more than that per line. After further digging, I found that switching to
Verizon’s unlimited plan got me down to around $35 per line so it ended up not being a better deal.</p>

<p>With the recent introduction of <a href="https://www.visible.com/party-pay">parties 🥳</a> that brought the per-line cost down to $25 and with 5
lines that was a savings of $50/month. I realize in hindsight that $50 probably isn’t enough to start messing with
services that have been working fine for a decade and replace them with services that are 2 years old, but 🤷‍♂️.
In my defense, though $50 a month would damn near covers my Busch Light bill.</p>

<p>So I’m off! But not before I check the twitters and read about some pretty <a href="https://twitter.com/smbrancati/status/1192499408144936965">nightmarish porting
experiences</a>. Reddit has <a href="https://www.reddit.com/r/Visible/comments/d0nkxh/porting_from_verizon_how_long_does_it_take/">some good ones
too</a>. I know 💡! I’ll just
get a new number. Like a fresh 🌼 start. To their credit that actually did work and they did have a pretty decent deal
on a new phone so that’s what I went with. The phone arrived on time, I put the sim in, tried to call the new number and 👎
there is a calling restriction on this line. A quick trip over to Visible customer service, aka twitter direct messages,
got me going with the first suggestion in their troubleshooting script which was to turn airplane mode on and back off. I guess it 
resets the network or something, but I was up and going in a short period of time.</p>

<p>At this point, I have a working number on Visible which looking back on it all was a small miracle. While I was fine
with a new number; it’s quite the opposite for my family (maybe one family member in particular). So here we go…I’m going
to port all the numbers over to Visible. That leads into the first annoyance with Visible which is the lack of a family plan.
Each number is its own account and its own bill. Luckily we have the gmail + trick so I can manage all of them from one
email address.</p>

<p>The porting requirements were the phone number, account number, and account pin. All of these were copied from the
Verizon site. Once it was requested it said it could take up to 48 hours…</p>

<p>🕛 🕒 🕕 🕘 🕛 🕒 🕕 🕙</p>

<p>In the hours leading up to 48 hour mark I asked for a status 3 times. Finally, after 3 days, one of the agents informed 
me that the porting process was never started because the account numbers were incorrect (remember that copy/paste thing from above).</p>

<p>With the twitter and reddit stories and now my own experience I had zero confidence that the porting process was going
to work or even did work ever for that matter. Experiment over. I asked them for the account number and pin so I could 
port the new number back over to my Verizon line. Why not forget about the new Visible number and close the account? 
Because I had wanted a new number anyway and I had already notified everyone of the new number so I didn’t want to 
send out another “jk lol nm” message.</p>

<p>After a couple of “we hate to see you go” messages, I got the info I needed to port the number over to Verizon. I tried that
and was greeted with a “We can’t do that. There is an existing installment agreement associated with the number”. 🤬
Back to Visible CS on twitter. They will have to escalate a case to get that number released which could take up to
24 hours. They tell me they marked it as critical so I’m not waiting too long 🙄. That was at 6:30 am on Thursday. I
check my email early Friday morning and find a “Thank you and goodbye” email. They. Close. My. Fucking. Account. So now
I have a phone with no service. Luckily I’m kind of an asshole so not a lot of people try to contact me and the chances
are that they didn’t even update my contact info anyway.</p>

<p>No worries I’ll just port the number over to Verizon now. I head to their site and try the port again and it tells me I
can’t do it until 24 hours from the past attempt. JFC. That was only a couple of hours away so I wait. I try the port at 6:30
on Friday morning and it seems to go through and says it can take up to 24 hours. All of these multi-hour ports are
really weird considering, from what I’ve read, that Verizon actually owns Visible.</p>

<p>Afternoon comes and I’m starting to realize this ain’t happening. I contact Verizon customer service and they give me a
number to the port authority (get it?) where I can check the status of an existing port. I do that and it tells me that
it can’t be completed because the number is inactive on the previous carrier. The fuck? You know when a really good time is 
to tell folks about all of these porting errors is? Maybe when they make the damn request? Technology is hard. Anyway, I 
get a hold of a real person there and after several minutes of being on hold, she tells me…wait for it…the port can’t 
be completed because the number is inactive on the previous carrier. Thanks.</p>

<p>Back to twitter DM. Visible CS says you’ll have to reactive the account (ya know…the one they just god damned closed)
in order to port into Verizon, but no worries if you don’t use the service they’ll be happy to refund the initial month.
Yeah, right.</p>

<p>I just want this to be over so I give up and use my crusty old original number. But then I think 🤔 what if this
number gets activated in the future and that port request is still out there. I would not be one bit surprised for that
request to go through 2 months from now (that’s assuming that Visible stays in business for 2 more months). So I
call the Verizon port people and get this really helpful (not in a sarcastic way) dude that cancels both the port
request and the number change order that was on my account. He asks me about why I was changing numbers and I mention
the Visible dumpster fire and surprise, surprise he’s heard about it. We crack open a couple of Busch Lights and catch up on
old times…wait, that last part didn’t happen.</p>

<p>In summary, I’m out $25, but I did get a decent deal on a phone (hopefully no Visible juice leaked on it and cursed it).
Some friends and family that changed my number now won’t be able to get in touch with me, but I have confidence
that they’ll figure it out.</p>

<p>Visible…the good parts:</p>

<ul>
  <li>$25/month service.</li>
  <li>Unlimited data on Verizon LTE</li>
</ul>

<p>Visible…the bad parts:</p>

<ul>
  <li>Porting is a 💩 show. It seems to be especially bad if you’re with Verizon already.</li>
  <li>Customer service is a joke. Don’t get me wrong, I really dislike calling any customer service and talking to real humans, but when you need to it’s pretty damn handy to have that available to you. I imagine customer service through Facebook or Twitter saves a ton of money, but the front line reps have no clue what’s going on. They have their scripts and anything outside of that is a ticket into specialists.</li>
  <li>Lack of a family/friends plan is annoying. Needing to create 5 separate accounts and get charged 5 separate times is a hassle. The party pay is so close to this why not just go all in so you’re not hooking up with strangers that may or may not stay on the service to save your $15?</li>
  <li>LTE only. Granted this probably wouldn’t hurt me 99.8% of the time, but if you go anywhere outside of the Verizon LTE network you have no service.</li>
  <li>Network flakiness. There are multiple complaints about needing to use the airplane mode trick daily to regain service. Although it is the Verizon network, it’s not quite the same as being a Verizon customer.</li>
  <li>Party pay actually working seems to be hit and miss. I didn’t get far enough to experience this, but you should check out the Reddit threads and consider the risk for yourself.</li>
</ul>

<p>My recommendation? Stay away. Far away. And if this company was formed just to make Verizon look better then it worked (and a genius move).</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Vim ❤️ ESLint ❤️ Prettier]]></title>
      <link href="https://darrinholst.com/blog/2018/04/01/vim-eslint-prettier/"/>
    

    
    <updated>2018-04-01T07:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2018/04/01/vim-eslint-prettier</id>
    <content type="html"><![CDATA[<p>If you’re on a team or project that is still using eslint for formatting rules then first…I’m sorry.
Second, this will show you how to get vim setup to autoformat code using both eslint and
<a href="https://prettier.io/">prettier</a>. I’ll skip the prettier pitch for now. Use it.</p>

<p>The first thing you’ll need is is a vim plugin that can format code. I use
<a href="https://github.com/sbdchd/neoformat">neoformat</a>.</p>

<div class="language-vimscript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Plugin <span class="s1">'sbdchd/neoformat'</span>
</code></pre></div></div>

<p>Neoformat uses external tools to format a buffer based on the filetype. The list of
<a href="https://github.com/sbdchd/neoformat#supported-filetypes">supported filetypes</a> is quite extensive.
You’ll see for javascript these formatters are available.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>js-beautify, prettier, prettydiff, clang-format, esformatter, prettier-eslint, eslint_d standard
</code></pre></div></div>

<p>In our case prettier and eslint_d are the ones that we’re interested in. I configure it to only look
for those two so it’s not trying to use formatters that aren’t installed. Neoformat will run each
formatter in sequence <em>until</em> one succeeds.</p>

<div class="language-vimscript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="nv">g:neoformat_enabled_javascript</span> <span class="p">=</span> <span class="p">[</span><span class="s1">'prettier'</span><span class="p">,</span> <span class="s1">'eslint_d'</span><span class="p">]</span>
</code></pre></div></div>

<p>We need the formatting tools installed locally so let’s do that…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm i -D prettier eslint_d
</code></pre></div></div>

<p><a href="https://github.com/mantoni/eslint_d.js"><code class="language-plaintext highlighter-rouge">eslint_d</code></a> works the same as <code class="language-plaintext highlighter-rouge">eslint</code> would except it
spins up a small server in the background to use on subsequent calls. This is needed because we
don’t want our “format on save” taking almost a second.</p>

<p>Now it’s time to try it.</p>

<figure class="full">
  <img src="/images/vim_prettier_eslint/prettier.gif" />
  <figcaption>First time using asciicast and I couldn't find the make me look like a good typist option</figcaption>
</figure>

<p>You can see that invoking <code class="language-plaintext highlighter-rouge">:Neoformat</code> will reformat the buffer with the default prettier config by
removing the blank line and inserting the semicolon. The problem is when we have conflicting rules.
Suppose we have the following eslint rule…</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"rules"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"quotes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"error"</span><span class="p">,</span><span class="w"> </span><span class="s2">"single"</span><span class="p">]</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>The eslint rules say that it wants single quotes.  I mentioned above that neoformat will only run 
until one formatter succeeds. We need to tell it to run <em>all</em> formatters with…</p>

<div class="language-vimscript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="nv">g:neoformat_run_all_formatters</span> <span class="p">=</span> <span class="m">1</span>
</code></pre></div></div>

<p>Now if we run it again you’ll see that both prettier and eslint formatting is applied by the
changing of double quotes to single quotes.</p>

<p><img src="/images/vim_prettier_eslint/eslint.gif" alt="eslint" /></p>

<p>In order to format on save you can add an <code class="language-plaintext highlighter-rouge">autocmd</code> to run <code class="language-plaintext highlighter-rouge">Neoformat</code> on buffer pre write like
so…</p>

<div class="language-vimscript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">au</span> <span class="nb">BufWritePre</span> *<span class="p">.</span><span class="nb">js</span><span class="p">,</span>*<span class="p">.</span><span class="k">ts</span><span class="p">,</span>*<span class="p">.</span>scss<span class="p">,</span>*<span class="p">.</span>rb Neoformat
</code></pre></div></div>

<p>Now every time you save both prettier and eslint formatters will run with eslint having the final
say since it’s last in the neoformat list.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Testing Angular Components with Mocha, Webpack and jsdom]]></title>
      <link href="https://darrinholst.com/blog/2017/11/09/testing-angular-components/"/>
    

    
    <updated>2017-11-09T08:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2017/11/09/testing-angular-components</id>
    <content type="html"><![CDATA[<p>The following Angular component shows a logout button if there is a logged in user.</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span><span class="nx">Component</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@angular/core</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span><span class="nx">select</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@angular-redux/store</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span><span class="nx">Observable</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">rxjs/Observable</span><span class="dl">'</span><span class="p">;</span>

<span class="p">@</span><span class="nd">Component</span><span class="p">({</span>
  <span class="na">selector</span><span class="p">:</span> <span class="dl">'</span><span class="s1">app-header</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">template</span><span class="p">:</span> <span class="s2">`
    &lt;mat-toolbar fxLayoutAlign="end center"&gt;
      &lt;a class="logo" fxFlex routerLink="/"&gt;&lt;img src="logo.png"&gt;&lt;/a&gt;
      &lt;button *ngIf="isLoggedIn()" mat-icon-button [matMenuTriggerFor]="menu"&gt;&lt;i class="fa fa-bars"&gt;&lt;/i&gt;&lt;/button&gt;
    &lt;/mat-toolbar&gt;

    &lt;mat-menu #menu="matMenu"&gt;
      &lt;button mat-menu-item routerLink="/logout" title="logout"&gt;&lt;i class="fa fa-sign-out"&gt;&lt;/i&gt; Logout&lt;/button&gt;
    &lt;/mat-menu&gt;
  `</span>
<span class="p">})</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">AppHeaderComponent</span> <span class="p">{</span>
  <span class="k">private</span> <span class="nx">user</span><span class="p">:</span> <span class="kr">any</span><span class="p">;</span>
  <span class="p">@</span><span class="nd">select</span><span class="p">()</span> <span class="k">private</span> <span class="nx">user$</span><span class="p">:</span> <span class="nx">Observable</span><span class="o">&lt;</span><span class="kr">any</span><span class="o">&gt;</span><span class="p">;</span>

  <span class="nx">ngOnInit</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">user$</span><span class="p">.</span><span class="nx">subscribe</span><span class="p">(</span><span class="nx">user</span> <span class="o">=&gt;</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">user</span> <span class="o">=</span> <span class="nx">user</span><span class="p">));</span>
  <span class="p">}</span>

  <span class="nx">isLoggedIn</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="o">!!</span><span class="k">this</span><span class="p">.</span><span class="nx">user</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Supposing I want to test the two different states I might come up with a test like:</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span><span class="nx">TestBed</span><span class="p">,</span> <span class="nx">ComponentFixture</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@angular/core/testing</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span><span class="nx">By</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@angular/platform-browser</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span><span class="nx">NgReduxTestingModule</span><span class="p">,</span> <span class="nx">MockNgRedux</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@angular-redux/store/testing</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span><span class="nx">expect</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">chai</span><span class="dl">'</span><span class="p">;</span>

<span class="k">import</span> <span class="p">{</span><span class="nx">MaterialModule</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">core/material.module</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span><span class="nx">AppHeaderComponent</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">core/app-header.component</span><span class="dl">'</span><span class="p">;</span>

<span class="nx">describe</span><span class="p">(</span><span class="dl">'</span><span class="s1">app-header</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">let</span> <span class="na">fixture</span><span class="p">:</span> <span class="nx">ComponentFixture</span><span class="o">&lt;</span><span class="nx">AppHeaderComponent</span><span class="o">&gt;</span><span class="p">;</span>

  <span class="nx">beforeEach</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">TestBed</span><span class="p">.</span><span class="nx">configureTestingModule</span><span class="p">({</span>
      <span class="na">imports</span><span class="p">:</span> <span class="p">[</span><span class="nx">MaterialModule</span><span class="p">,</span> <span class="nx">NgReduxTestingModule</span><span class="p">],</span>
      <span class="na">declarations</span><span class="p">:</span> <span class="p">[</span><span class="nx">AppHeaderComponent</span><span class="p">]</span>
    <span class="p">});</span>

    <span class="nx">fixture</span> <span class="o">=</span> <span class="nx">TestBed</span><span class="p">.</span><span class="nx">createComponent</span><span class="p">(</span><span class="nx">AppHeaderComponent</span><span class="p">);</span>
  <span class="p">});</span>

  <span class="nx">it</span><span class="p">(</span><span class="dl">'</span><span class="s1">should show a menu button if logged in</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">expectUserToBe</span><span class="p">({</span><span class="na">id</span><span class="p">:</span> <span class="dl">'</span><span class="s1">anything</span><span class="dl">'</span><span class="p">});</span>
    <span class="kd">const</span> <span class="nx">button</span> <span class="o">=</span> <span class="nx">findToolbarMenuButton</span><span class="p">();</span>
    <span class="nx">expect</span><span class="p">(</span><span class="nx">button</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">have</span><span class="p">.</span><span class="nx">length</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
  <span class="p">});</span>

  <span class="nx">it</span><span class="p">(</span><span class="dl">'</span><span class="s1">should not show a menu button if not logged in</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">expectUserToBe</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">button</span> <span class="o">=</span> <span class="nx">findToolbarMenuButton</span><span class="p">();</span>
    <span class="nx">expect</span><span class="p">(</span><span class="nx">button</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">have</span><span class="p">.</span><span class="nx">length</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">});</span>

  <span class="kd">function</span> <span class="nx">findToolbarMenuButton</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">fixture</span><span class="p">.</span><span class="nx">detectChanges</span><span class="p">();</span>
    <span class="k">return</span> <span class="nx">fixture</span><span class="p">.</span><span class="nx">debugElement</span><span class="p">.</span><span class="nx">queryAll</span><span class="p">(</span><span class="nx">By</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="dl">'</span><span class="s1">mat-toolbar button</span><span class="dl">'</span><span class="p">));</span>
  <span class="p">}</span>

  <span class="kd">function</span> <span class="nx">expectUserToBe</span><span class="p">(</span><span class="na">user</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">userSub</span> <span class="o">=</span> <span class="nx">MockNgRedux</span><span class="p">.</span><span class="nx">getSelectorStub</span><span class="p">([</span><span class="dl">'</span><span class="s1">user</span><span class="dl">'</span><span class="p">]);</span>
    <span class="nx">userSub</span><span class="p">.</span><span class="nx">next</span><span class="p">(</span><span class="nx">user</span><span class="p">);</span>
    <span class="nx">userSub</span><span class="p">.</span><span class="nx">complete</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<p>How do I run that? I don’t want to use karma because I don’t want to deal with a real browser for CI
reasons. I don’t want to use phantomjs for phantomjs reasons. There aren’t many headless chrome
tutorials out there currently which is probably the future. I want to use mocha since that is what I
use for all my non-browser tests.</p>

<p>Since we just need the DOM api <a href="https://github.com/tmpvar/jsdom">jsdom</a> should be good enough to get
this working. It wasn’t quite a straight forward as “just using jsdom”, so here’s what I had to do.</p>

<p>For the mocha part, I use <a href="https://github.com/zinserjan/mocha-webpack">mocha-wepback</a> to handle
bundling the app and running the tests. Oh yeah, you need to be using webpack for this too.</p>

<p>We don’t need all of the bells and whistles of what a full frontend webpack config might have in it
so I use a stripped down version of one. It looks like:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">nodeExternals</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">webpack-node-externals</span><span class="dl">'</span><span class="p">);</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">target</span><span class="p">:</span> <span class="dl">'</span><span class="s1">node</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">externals</span><span class="p">:</span> <span class="p">[</span><span class="nx">nodeExternals</span><span class="p">()],</span>

  <span class="na">resolve</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">extensions</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">.ts</span><span class="dl">'</span><span class="p">]</span>
  <span class="p">},</span>

  <span class="na">module</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">rules</span><span class="p">:</span> <span class="p">[</span>
      <span class="p">{</span>
        <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">ts$/</span><span class="p">,</span>
        <span class="na">exclude</span><span class="p">:</span> <span class="sr">/node_modules/</span><span class="p">,</span>
        <span class="na">loaders</span><span class="p">:</span> <span class="p">[</span>
          <span class="p">{</span>
            <span class="na">loader</span><span class="p">:</span> <span class="dl">'</span><span class="s1">awesome-typescript-loader</span><span class="dl">'</span><span class="p">,</span>
            <span class="na">options</span><span class="p">:</span> <span class="p">{</span><span class="na">configFileName</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">../tsconfig.json</span><span class="dl">'</span><span class="p">)}</span>
          <span class="p">},</span>
          <span class="dl">'</span><span class="s1">angular2-template-loader</span><span class="dl">'</span>
        <span class="p">]</span>
      <span class="p">}</span>
    <span class="p">]</span>
  <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>So after installing mocha-webpack go ahead and try it</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mocha-webpack \
  --webpack-config client/test/webpack.config.js \
  "client/test/unit/**/*.spec.ts"
</code></pre></div></div>

<p>Probably didn’t work. Angular needs a whole bunch of things to get the testing environment setup
so we’ll need a way to do that. For reasons that I’m unable to recall I
call this file <code class="language-plaintext highlighter-rouge">mocha-shim.js</code>. I <em>think</em> Angular ships with a jasmine shim so that’s maybe where I
got it from. Anyway, it’s the content that matters. Here’s what it looks like:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="p">{</span><span class="nx">JSDOM</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">jsdom</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nb">document</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JSDOM</span><span class="p">(</span><span class="dl">'</span><span class="s1">&lt;!doctype html&gt;&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nb">window</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nb">window</span><span class="p">;</span>

<span class="nb">global</span><span class="p">.</span><span class="nx">HTMLElement</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">HTMLElement</span><span class="p">;</span>
<span class="nb">global</span><span class="p">.</span><span class="nx">XMLHttpRequest</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">XMLHttpRequest</span><span class="p">;</span>
<span class="nb">global</span><span class="p">.</span><span class="nb">document</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nb">document</span><span class="p">;</span>
<span class="nb">global</span><span class="p">.</span><span class="nb">navigator</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nb">navigator</span><span class="p">;</span>
<span class="nb">global</span><span class="p">.</span><span class="nx">Node</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{};</span>
<span class="nb">global</span><span class="p">.</span><span class="nx">Node</span><span class="p">.</span><span class="nx">ELEMENT_NODE</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">global</span><span class="p">.</span><span class="nx">Event</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{};</span>

<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">core-js/es6</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">core-js/es7/reflect</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">zone.js/dist/zone</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">zone.js/dist/long-stack-trace-zone</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">zone.js/dist/proxy</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">zone.js/dist/sync-test</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">zone.js/dist/async-test</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">zone.js/dist/fake-async-test</span><span class="dl">'</span><span class="p">);</span>

<span class="kd">const</span> <span class="nx">testing</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">@angular/core/testing</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">browser</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">@angular/platform-browser-dynamic/testing</span><span class="dl">'</span><span class="p">);</span>

<span class="nx">testing</span><span class="p">.</span><span class="nx">TestBed</span><span class="p">.</span><span class="nx">initTestEnvironment</span><span class="p">(</span>
  <span class="nx">browser</span><span class="p">.</span><span class="nx">BrowserDynamicTestingModule</span><span class="p">,</span>
  <span class="nx">browser</span><span class="p">.</span><span class="nx">platformBrowserDynamicTesting</span><span class="p">()</span>
<span class="p">);</span>

<span class="nb">global</span><span class="p">.</span><span class="nb">window</span> <span class="o">=</span> <span class="nb">window</span><span class="p">;</span>
<span class="nb">global</span><span class="p">.</span><span class="nx">CSS</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>

<span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">hammerjs</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>

<p>You’ll see we’re setting up jsdom to get a browser environment and then setting a bunch of global
things that you’d find in a real browser. Then we require some things to “make it work”. To be
honest I copied most of this from that jasmine shim file so I couldn’t tell you for sure what
everything is doing here. I will tell you that order is important in this file. There’s also a few
lines at the bottom that you won’t need if you’re not using Material.</p>

<p>Now we need to require that file in our test runner. Don’t forget to install jsdom.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mocha-webpack \
  --webpack-config client/test/webpack.config.js \
  --require client/test/unit/helpers/mocha-shim.js \
  "client/test/unit/**/*.spec.ts"
</code></pre></div></div>

<p>That got us closer and we’d be done if there was only one test, but when it hits the second test we
get:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Error: Cannot configure the test module when the test module has already been instantiated. Make sure you are not using `inject` before `TestBed.configureTestingModule`.
</code></pre></div></div>

<p>One other thing that the jasmine integrations do for us out of the box is reset the testing
environment after each test. We’ll need to do that for mocha. I added a helper file that we can
include in the test runner.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span><span class="nx">getTestBed</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@angular/core/testing</span><span class="dl">'</span><span class="p">;</span>

<span class="nx">afterEach</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">getTestBed</span><span class="p">().</span><span class="nx">resetTestingModule</span><span class="p">();</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Our final command looks like…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mocha-webpack \
  --webpack-config client/test/webpack.config.js \
  --require client/test/unit/helpers/mocha-shim.js \
  --include client/test/unit/helpers/spec-helper.js \
  "client/test/unit/**/*.spec.ts"
</code></pre></div></div>

<p>…and we finally get the green we’ve been looking for</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  app-header
    ✓ should show a menu button if logged in
    ✓ should not show a menu button if not logged in

  2 passing (444ms)
</code></pre></div></div>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Deploying Node Apps to Heroku]]></title>
      <link href="https://darrinholst.com/blog/2017/11/03/deploying-node-apps-to-heroku/"/>
    

    
    <updated>2017-11-03T08:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2017/11/03/deploying-node-apps-to-heroku</id>
    <content type="html"><![CDATA[<figure class="full">
  <img src="/images/dumpster_fire/fire.jpg" />
  <figcaption>Nothing a little webpack can't fix.</figcaption>
</figure>

<p>On a recent episode of <a href="https://devchat.tv/adv-in-angular/aia-157-building-angular">Adventures in Angular</a>
the panelists discuss some of the frustrations encountered in deploying an Angular app to a production
environment. Heroku was mentioned as one of the hosting options which got my attention since that is what I’ve been
neck deep in for the last year. While it’s not as simple as just a <code class="language-plaintext highlighter-rouge">git push heroku master</code> that you
may have become used to in Rails, I’d argue that it’s not necessarily a bad thing. I would even say that it’s not the
dumpster fire that it was described as. Maybe a small trash can fire, but totally manageable and
sometimes pleasant.</p>

<p>This post is a documentation of my development, release,  and deployment cycle on these types of projects.
Your mileage may vary and if it doesn’t work for you I’m offering a 100% monetary refund. The
complete demo app is available at <a href="https://github.com/darrinholst/heroku-nodejs-build-demo">darrinholst/heroku-nodejs-build-demo</a>
and the library that I extracted out of it is available at <a href="https://github.com/darrinholst/heroku-nodejs-build">darrinholst/heroku-nodejs-build</a>.</p>

<p>I had a few high level goals/requirements for this process:</p>

<ul>
  <li>A Node backend optionally written in TypeScript because who knew that types were actually useful?</li>
  <li>Angular frontend just because that’s what I was used to at the time, but it can be adapted to
any hip new framework.</li>
  <li>Hosted on Heroku. You give up a little control using a PaaS, but the speed at which you can
prototype and transition to a production environment is <a href="https://www.youtube.com/watch?v=zYt0WbDjJ4E">nice</a>.</li>
  <li>PostgreSQL for persistence. Storing and manipulating JSON in PostgreSQL has become pretty darn good and it’s a first
class citizen in the Heroku ecosystem.</li>
  <li>A single command to build and test All The Things™. If this command runs without errors you have my
93% guarantee that it will work on any other machine that is aluminum and has a piece of fruit on
it somewhere.</li>
  <li>A single release artifact that can be deployed to any environment. This means that you shouldn’t
be manually changing any files to make it work in an environment.</li>
</ul>

<p>The obligatory caveats:</p>

<ul>
  <li>I don’t use the Angular CLI. This process was developed a few months before it was usable and it
makes me a little nervous to be locked in to a tool like that. This process could be adapted to
use the CLI if you just use it for component creation and bundling. See the next point for why I 
still wouldn’t use it for a development server.</li>
  <li>
    <p>I don’t use webpack-dev-server. Not sure why, just never got into it. I also have never
used a DVR (true story). Just a plain old boring web server that serves files. Maybe a little
similar to <a href="https://12factor.net/dev-prod-parity">how you’re going to be running in production</a>.</p>

    <p><em>How do you get through the day without hawt module replacement?</em> I manage. I just make sure all of my
states are represented by a unique url and then do a good old fashioned browser refresh…like an
animal. I do use the <code class="language-plaintext highlighter-rouge">--watch</code> option for webpack which makes incremental builds really fast. I
also use <a href="https://nodemon.io">nodemon</a> for reloading the backend when there are changes and 
<a href="https://www.browsersync.io">browsersync</a> for the frontend.</p>
  </li>
  <li>This was built out before Heroku announced support for containers. I may be Doing It Wrong™ now.</li>
</ul>

<h3 id="building-the-backend">Building the backend</h3>

<p>Let’s get this out of the way since there’s not a lot different going on from a normal express based
Node backend that you may have seen before. The only novel thing I’ve added is TypeScript support.
That means we now need a build process for our backend code. All of our building is handled by
webpack. Love it or hate it I’ve found if you stay just far enough out of the weeds it’s not that
bad.</p>

<p>This is the entire config for the backend side.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">nodeExternals</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">webpack-node-externals</span><span class="dl">'</span><span class="p">);</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">context</span><span class="p">:</span> <span class="nx">__dirname</span><span class="p">,</span>
  <span class="na">target</span><span class="p">:</span> <span class="dl">'</span><span class="s1">node</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">devtool</span><span class="p">:</span> <span class="dl">'</span><span class="s1">inline-source-map</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">externals</span><span class="p">:</span> <span class="p">[</span><span class="nx">nodeExternals</span><span class="p">()],</span>

  <span class="na">output</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">path</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">dist</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">},</span>

  <span class="na">resolve</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">extensions</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">.ts</span><span class="dl">'</span><span class="p">],</span>
    <span class="na">alias</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">src</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">src</span><span class="dl">'</span><span class="p">),</span>
      <span class="na">universal</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">../universal/src</span><span class="dl">'</span><span class="p">)</span>
    <span class="p">}</span>
  <span class="p">},</span>

  <span class="na">module</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">rules</span><span class="p">:</span> <span class="p">[{</span>
      <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">ts$/</span><span class="p">,</span>
      <span class="na">exclude</span><span class="p">:</span> <span class="sr">/node_modules/</span><span class="p">,</span>
      <span class="na">loaders</span><span class="p">:</span> <span class="p">[</span>
        <span class="p">{</span>
          <span class="na">loader</span><span class="p">:</span> <span class="dl">'</span><span class="s1">awesome-typescript-loader</span><span class="dl">'</span><span class="p">,</span>
          <span class="na">options</span><span class="p">:</span> <span class="p">{</span><span class="na">silent</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="na">configFileName</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">tsconfig.json</span><span class="dl">'</span><span class="p">)}</span>
        <span class="p">}</span>
      <span class="p">]</span>
    <span class="p">}</span>
  <span class="p">]}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><a href="http://jlongster.com/Backend-Apps-with-Webpack--Part-I">Backend Apps with Webpack</a> is a great post
to learn what is going on here, but the tl;dr is JavasScript and/or TypeScript files go in and
<code class="language-plaintext highlighter-rouge">dist/index.js</code> comes out ready to run with Node.</p>

<p>Other than that it’s a traditional <code class="language-plaintext highlighter-rouge">Controller / Service / Repository</code> stack.</p>

<p>Authentication is handled by <a href="https://jwt.io">jwt</a>.</p>

<p>Config files are an important part of one of the requirements of having a single release artifact.
Environment variables are the other player in staying away from manually changing files. See <a href="https://12factor.net/config">The
Twelve-Factor App</a> for why that’s important. We use
<a href="https://github.com/lorenwest/node-config">node-config</a> to handle that. An example of how that looks
in practice is <a href="https://github.com/darrinholst/heroku-nodejs-build-demo/blob/master/server/config/default.js">here</a>.
The take away is that anything that can change or is sensitive should not be hard coded in your
source code.</p>

<p>I won’t go in to a lot of detail on persistence since it’s not the point of this post. Just know
that we use <a href="https://github.com/vitaly-t/pg-promise">pg-promise</a> for the runtime part and
<a href="https://github.com/db-migrate/node-db-migrate#readme">db-migrate</a> to handle schema management.
Personally, I don’t have a bunch of schema management since I usually just opt for storing JSON
documents and handling it on the frontend side. Also, I’m not a DBA.</p>

<h3 id="building-the-frontend">Building the frontend</h3>

<p>The frontend side is where things get a little more complex when it comes to webpack. I’ll spare you
scrolling past the entire config, but it’s <a href="https://github.com/darrinholst/heroku-nodejs-build-demo/blob/master/client/webpack.config.js">here</a>
if you want to follow along. I’m not a big fan of injecting css with javascript that webpack steers
you towards so there’s some config in there to extract it out to it’s own file with <code class="language-plaintext highlighter-rouge">extract-text-webpack-plugin</code>. There’s also
some junk in there to deal with development vs production builds since we usually don’t need
minifying and external sourcemaps  when we’re in development mode.</p>

<p>Just like the backend, (Java|Type)Script, Sass, and whatever else you can dream up goes in and bundled 
files come out. This time we’re outputing es5 for the browser and putting the output directly
into the backend’s <code class="language-plaintext highlighter-rouge">public</code> directory so that whole file serving thing can work.</p>

<p>Follow your framework of choice guidelines to build out the frontend side. You’re on your own there,
but for a small fee I can help you out with that.</p>

<h3 id="when-your-code-cant-decide-if-its-backend-or-frontend">When your code can’t decide if it’s backend or frontend</h3>

<p>The only other source code related thing that I like to add is a <code class="language-plaintext highlighter-rouge">universal</code> directory that any code
that can be used by both the backend and frontend can live. The example repo has a simple utility
class, but in some of my real projects this is where I’ve put model objects. This is handy if you
want to share validation code between backend and frontend or if you need those models for building
anything on the backend (what’s a web app if it doesn’t have a pdf generator 🙄). You’ll find another
webpack config in this directory, but that’s just used for running tests which we’ll get into later.
Both the <code class="language-plaintext highlighter-rouge">webpack.config.js</code> and <code class="language-plaintext highlighter-rouge">tsconfig.json</code> in 
<a href="https://github.com/darrinholst/heroku-nodejs-build-demo/blob/master/client/webpack.config.js#L33">the</a>
<a href="https://github.com/darrinholst/heroku-nodejs-build-demo/blob/master/client/tsconfig.json#L16">frontend</a>
<a href="https://github.com/darrinholst/heroku-nodejs-build-demo/blob/master/server/webpack.config.js#L18">and</a>
<a href="https://github.com/darrinholst/heroku-nodejs-build-demo/blob/master/server/tsconfig.json#L16">backend</a>
reference this directory so it’s available either place. Magic!</p>

<p><img src="/images/dumpster_fire/magic.gif" /></p>

<h3 id="mvn-verify">mvn verify</h3>

<p>Source code and build config is all taken care of, now let’s get back to the one command to verify
everything. Verify comes from my dark days as a Java developer where there was one maven command
(phase?) to compile, test, and package whatever you were delivering. I’ve always thought this was a
good idea so it has tagged along with me through whatever language I’ve been working in (the name,
not maven). Also, if somebody breaks the build you can snidely drop them a “Did you even run
verify?”</p>

<p><code class="language-plaintext highlighter-rouge">scripts/verify</code> is where we’ll stick this script because it’s a script and it’s named verify <code class="language-plaintext highlighter-rouge">¯\_(ツ)_/¯</code> . It goes something like…</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>

<span class="nv">RESET</span><span class="o">=</span><span class="s1">$'</span><span class="se">\e</span><span class="s1">[0m'</span>
<span class="nv">BLUE</span><span class="o">=</span><span class="s1">$'</span><span class="se">\e</span><span class="s1">[1;34m'</span>

<span class="nb">printf</span> <span class="s2">"</span><span class="se">\n</span><span class="k">${</span><span class="nv">BLUE</span><span class="k">}</span><span class="s2">[%s] installing dependencies:</span><span class="k">${</span><span class="nv">RESET</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">date</span> +%T<span class="si">)</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="se">\</span>
yarn <span class="nb">install</span> <span class="o">&amp;&amp;</span> <span class="se">\</span>
yarn run <span class="nt">-s</span> clean <span class="o">&amp;&amp;</span> <span class="se">\</span>
yarn run <span class="nt">-s</span> lint <span class="o">&amp;&amp;</span> <span class="se">\</span>
yarn run <span class="nt">-s</span> <span class="nb">test</span>:unit <span class="o">&amp;&amp;</span> <span class="se">\</span>
yarn run <span class="nt">-s</span> <span class="nb">test</span>:integration <span class="o">&amp;&amp;</span> <span class="se">\</span>
yarn run <span class="nt">-s</span> build:prod <span class="o">&amp;&amp;</span> <span class="se">\</span>
yarn run <span class="nt">-s</span> <span class="nb">test</span>:e2e <span class="o">&amp;&amp;</span> <span class="se">\</span>
<span class="nb">printf</span> <span class="s2">"</span><span class="se">\n</span><span class="k">${</span><span class="nv">BLUE</span><span class="k">}</span><span class="s2">[%s] 🎉  👏  😻  </span><span class="k">${</span><span class="nv">RESET</span><span class="k">}</span><span class="se">\n\n</span><span class="s2">"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">date</span> +%T<span class="si">)</span><span class="s2">"</span>
</code></pre></div></div>

<p>This is where you’ll define all the steps as to what verifying means to your particular project.
Don’t forget the emojis…they’re important.</p>

<p>I’m using npm/yarn’s built in script running here. Check out <a href="https://github.com/testdouble/scripty">scripty</a>
if you’ve tried this before, but ended up gouging yours eyes out after encoding shell scripts in
JSON format.</p>

<p>Verify is at the minimum what you’ll do before you push your changes up. If it’s fast enough you’ll
do it a lot more than that. I’ve found that the production webpack build and e2e tests are sufficiently slow enough
to deter that and I usually just run the collection of tests that are going to be affected by what
I’m working on.</p>

<h3 id="testing">Testing</h3>

<p>This is as good of time as any to talk about testing. Ready? Do it.</p>

<p>I always start out with good intentions of building a <a href="https://martinfowler.com/bliki/TestPyramid.html">Test Pyramid</a>
although sometimes my pyramid ends up looking more blocky than I want. There’s no better feeling
than running thousands of tests in under a second. That warm, fuzzy feeling usually carries you all the
way through waiting for your end to end tests to complete. (Who tf put those in again?). The
<a href="https://blog.kentcdodds.com/write-tests-not-too-many-mostly-integration-5e8c7fff591c">confidence</a>
from e2e tests is pretty tempting.</p>

<p>As for tooling, I’ve settled on <a href="https://github.com/zinserjan/mocha-webpack#readme">mocha-webpack</a>
for all the unit and integration testing and <a href="http://www.protractortest.org/#/">protractor</a> + 
<a href="https://github.com/cucumber/cucumber-js">cucumber</a> for end to end testing.</p>

<p>Testing is such a large and nuanced subject that I’ll just leave it at that. There are examples in the demo
project. Feel free to hit me up with any questions.</p>

<h3 id="packaging">Packaging</h3>

<p>Also probably coming out of the good ol’ Java days is the single release artifact which was the
<code class="language-plaintext highlighter-rouge">.war</code>. Having 50 different effing environments to deploy to a few years ago helped get it through
my head that there was no sane or safe way of making manual changes after a deployment.</p>

<p>Up until this point everything…config, verify, etc…has been local to your project. This stuff is
usually unique to the project, but I feel like the process of packaging, releasing, and deploying could
be extracted to a set of generic steps and parameterized to specify what’s unique to your situation.
Especially since we’re targeting Heroku here. The package that came out of this is available 
at <a href="https://github.com/darrinholst/heroku-nodejs-build">darrinholst/heroku-nodejs-build</a>.</p>

<p>Once installed you’ll have access to the <code class="language-plaintext highlighter-rouge">package</code>, <code class="language-plaintext highlighter-rouge">release</code>, and <code class="language-plaintext highlighter-rouge">deploy</code> scripts so your scripts
section of <code class="language-plaintext highlighter-rouge">package.json</code> will need these additions:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">    </span><span class="nl">"package"</span><span class="p">:</span><span class="w"> </span><span class="s2">"node_modules/heroku-nodejs-build/scripts/package"</span><span class="err">,</span><span class="w">
    </span><span class="nl">"release"</span><span class="p">:</span><span class="w"> </span><span class="s2">"node_modules/heroku-nodejs-build/scripts/release"</span><span class="err">,</span><span class="w">
    </span><span class="nl">"deploy"</span><span class="p">:</span><span class="w"> </span><span class="s2">"node_modules/heroku-nodejs-build/scripts/deploy"</span><span class="w">
</span></code></pre></div></div>

<p>Its only requirements is that you have Docker installed locally and a <code class="language-plaintext highlighter-rouge">scripts/verify</code> script
exists. Docker is needed because we need the <a href="https://hub.docker.com/r/heroku/heroku/">heroku/heroku</a>
image so that we can build a <a href="https://devcenter.heroku.com/articles/slug-compiler">slug</a> that the Heroku
dyno manager knows what to do with. Docker is also nice in that the only dependency (besides node/npm) you
needs is Docker itself. When setting this up in a CI environment I just tell it to run
<code class="language-plaintext highlighter-rouge">npm install &amp;&amp; npm run package &amp;&amp; npm run release</code>.</p>

<p><em>Side note: before I extracted these scripts to an npm package I didn’t even need Node installed on CI.</em></p>

<p>The <code class="language-plaintext highlighter-rouge">package</code> script will run <code class="language-plaintext highlighter-rouge">scripts/verify</code> from earlier, but local to the docker container this
time. If it runs successfully it will then tar everything up into a slug and put it in the <code class="language-plaintext highlighter-rouge">build</code>
directory.</p>

<h3 id="releasing">Releasing</h3>

<p>Releasing is simply taking those artifacts built from <code class="language-plaintext highlighter-rouge">package</code> and storing them somewhere. That is
what the <code class="language-plaintext highlighter-rouge">release</code> script does. It uses the <a href="https://github.com/blog/1547-release-your-software">GitHub Releases</a>
infrastructure for storage. This is where your deployable artifacts will live and this is where the
<code class="language-plaintext highlighter-rouge">deploy</code> script will retrieve them from when deploying. It will also assign it a sequential version
number and tag the repo with that so you have a complete trail of everything.</p>

<p>It will need a couple of environment variables set to tell it about which GitHub repo you’re working
with and a token for authentication. See the <a href="https://github.com/darrinholst/heroku-nodejs-build#usage">README</a> for details.</p>

<h3 id="deploying">Deploying</h3>

<p>Almost done, hang in there. The act of deploying is just choosing a release and telling the <code class="language-plaintext highlighter-rouge">deploy</code>
script which Heroku app you want to deploy to. As mentioned earlier, I’m guessing the majority of
people know how to deploy to Heroku by the ol’ <code class="language-plaintext highlighter-rouge">git push heroku master</code>. What that is doing is
hooking into that push, detecting what type of project it is, choosing a
<a href="https://devcenter.heroku.com/articles/buildpacks">buildpack</a>, using that buildpack to create a
slug, and then running that slug on a dyno. What our <code class="language-plaintext highlighter-rouge">deploy</code> script does is skip the building of
the slug part since we already have a slug from the <code class="language-plaintext highlighter-rouge">package</code> step, downloads the release that we
want from GitHub and uses that pre built slug to run on a dyno.</p>

<p><em>Why not just use Heroku’s Node buildpack?</em> - because we have a non trivial build process for both
our backend and frontend and it will likely timeout with anything other than a simple app. Also, you
probably don’t want to be building your application as a part of your deploy. You already know that
you have a good build since you ran all of your tests against it in the <code class="language-plaintext highlighter-rouge">package</code> step. Just
deploy it [here] please. Although not as relevant now with the introduction of lockfiles with yarn
and npm 5+, another benefit of doing it this way is that your complete dependency tree is locked in
at <code class="language-plaintext highlighter-rouge">package</code> time. Even with lockfiles installing stuff from the scary internet at deploy time
should still make you raise an eyebrow.</p>

<p><img src="/images/dumpster_fire/eyebrow.jpg" /></p>

<h3 id="drink-a-">Drink a 🍺</h3>

<p>You deserve it for making it this far. There are a few things that I didn’t cover like slack
notifications, trimming the size of the slug, uploading sourcemaps, etc., but you’re smart you’ll
figure it out. Drop in a comment, GitHub issue, or email with any suggestions.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Remote is still a tough row to hoe]]></title>
      <link href="https://darrinholst.com/blog/2017/04/12/remote-chapter-2/"/>
    

    
    <updated>2017-04-12T08:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2017/04/12/remote-chapter-2</id>
    <content type="html"><![CDATA[<figure class="full">
  <img src="/images/remote2/hoe.jpg" />
  <figcaption>&nbsp;</figcaption>
</figure>

<p>It’s been a little over 3 years since I was struck down with the remote 🐛 and wrote down my <a href="http://darrinholst.com/blog/2014/02/18/remote/">thoughts</a> on why it was the greatest thing <em>evah</em>. All of those things are still true: I still hate a forced commute, I still love having the option to be able to get my kids ready for school every morning, and I still value the health benefits over the traditional workplace lunch song and dance. I continue to hear more and more and read more and more about #remotelife and the benefits all these employees are realizing. Plus all the benefits the employers are realizing by having happy and content employees. The recent <a href="https://stackoverflow.com/insights/survey/2017/#work-what-developers-value-in-compensationbenefits">Stack Overflow Developer Survey</a> shows remote options ranking #2 in valuable compensation/benefits. Another thing is still true even though it wasn’t mentioned in my first post: It’s harder than ever to find a remote friendly job.</p>

<h2 id="-or-">🐔 or 🥚?</h2>
<p>From my experience it is a chicken and egg game where an employer is not going to hire on a remote employee to a collocated team and a collocated team is not going to suddenly convert to remote (or even gradually convert…has the 1 day a week thing actually ever converted to full time IRL?). Given the huge talent gap that I keep hearing about in our industry there is a relatively minuscule percentage of opportunities where remote is an option (I mean…assuming I was searching for such things). For all the chatter I hear, I can’t help to think that we are just a very vocal minority. Maybe the survey suffers from the <a href="https://en.wikipedia.org/wiki/Healthy_user_bias">healthy user bias</a> that we see in health studies. Are all you remote people slacking off so much that you have time to take a survey?</p>

<h2>📡</h2>
<p>On the “bringing the remote employee on to a collocated team” thing: You might think <em>I can make that work. I’m a special ❄️</em>. There’s a 99.9% chance you’re wrong on that. Don’t do it. It’s tempting. I know. I spent over a year as a satellite employee and it wasn’t my most joyous times as a developer. You are indeed a special ❄️, but not in the good way. A quote from the excellent <a href="https://www.martinfowler.com/articles/remote-or-co-located.html">blog post</a> from <a href="https://www.martinfowler.com/">Martin Fowler</a>:</p>

<blockquote>
  <p>It’s very difficult to get satellite workers to be effective. With most people co-located, most communication will happen within the co-located team. I hardly ever hear of this model without the satellite person getting increasingly detached. If their work is very autonomous, that will reduce the problem. It is also wise to ensure satellite people make regular visits to the onsite team, at least a couple of times a month. But in most cases it seems best as a temporary measure.</p>
</blockquote>

<h2 id="-1">😕</h2>
<p>I do have to call out that it’s not always the people in charge of hiring that’s crushing all of our hopes and dreams. You’re probably not going to believe this, but there are actually people out there that enjoy going to an office and interacting with other humans all day. These people are called extroverts. For us introverts we <em>can</em> do this and often do a lot of times. It’s just that we don’t flourish in these situations. We all fall somewhere on the extrovert/introvert spectrum and it takes all kinds to be successful (think the Steve Jobs/Steve Wozniak combo). There is no wrong end to fall on, just keep that spectrum in mind when searching or hiring for a remote team. A lot more on this kind of stuff in <a href="https://www.amazon.com/Quiet-Power-Introverts-World-Talking-ebook/dp/B004J4WNL2/ref=sr_1_1?ie=UTF8&amp;qid=1492029844&amp;sr=8-1&amp;keywords=quiet">Quiet</a>. TL;DR? <a href="https://www.youtube.com/watch?v=eQH2U-kmBdY">Watch this</a>. Drawing from purely anecdotal evidence I believe there’s a strong correlation between introversion and remote.</p>

<h2 id="-2">🤷</h2>
<p>So what do we do? Fiik. Do we wait a couple of generations for all the Cosmo Spacelys to retire? Good for our grandkids…not so good for us. Do we wait for the industry to have their epiphany and start seeking us? It worked for Agile 😏.</p>

<p>A lot of questions, not too many answers. It’s always a people problem is the only thing I can come up with.</p>
]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Web Working with Webpack]]></title>
      <link href="https://darrinholst.com/blog/2016/09/11/web-worker/"/>
    

    
    <updated>2016-09-11T08:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2016/09/11/web-worker</id>
    <content type="html"><![CDATA[<h3 id="the-problem">The Problem</h3>

<p>You have a computational intense piece of javascript that is blocking browser interactions and
animations and making you question why you even try building desktop class web applications. In my case
I was trying to bring spreadsheet-like functionality into an application complete with formulas that
referenced other formulas that referenced other formulas to the brink of infinity. I ended up needing
to calculate tens of thousands of “cells” to get the data I needed.
While these calculations can usually complete in under 500 milliseconds (on a fast
browser/computer), a 1/2 second where the browser can’t do anything makes for a less than ideal
experience. (Think back in the day when you tried to use <code class="language-plaintext highlighter-rouge">async: false</code> on your ajax requests
because you couldn’t figure this callback stuff out. Was I the only one to try that? 🤔)</p>

<h3 id="solution-1---settimeout">Solution #1 - setTimeout</h3>

<p>In a server or native application we’d fire up a new thread to punt all of these computations
to. The browser, for better or for worse, is all like #lolThreads. I was not familiar enough with web
workers at the time to immediately reach for it so I improvised with the <code class="language-plaintext highlighter-rouge">setTimeout</code>
trick. It went something like:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">calculate</span><span class="p">(</span><span class="nx">years</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">processYear</span><span class="p">(</span><span class="nx">years</span><span class="p">,</span> <span class="p">{},</span> <span class="nx">callback</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">processYear</span><span class="p">(</span><span class="nx">years</span><span class="p">,</span> <span class="nx">results</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">years</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">doAllTheThingsForYear</span><span class="p">(</span><span class="nx">years</span><span class="p">.</span><span class="nx">shift</span><span class="p">(),</span> <span class="nx">results</span><span class="p">);</span>
    <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">processYear</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">years</span><span class="p">,</span> <span class="nx">results</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="nx">callback</span><span class="p">(</span><span class="nx">results</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This actually worked quite well. It uses <code class="language-plaintext highlighter-rouge">setTimeout</code> to give up control after each year and lets the
browser do all the things it needs to do. Although it works well it still felt a little hackish and
assumes you have a good seam like processing over a number of years to give up control at. Also, for
our tests we don’t want to just give away milliseconds like that because they add up over time.</p>

<h3 id="solution-2---web-worker">Solution #2 - web worker</h3>

<p>So I let the setTimeout hack ride for a week or two before I listened to this <a href="https://devchat.tv/adv-in-angular/108-aia-web-workers-in-angular-with-torgeir-helgevold">Adventures in
Angular</a>
episode where they talked about web workers in Angular. They spent a good amount of time trying to
come up with real world examples of where web workers would help. As I listened it occurred to me
that I was sitting on one of the quintessential examples…a spreadsheet…so it made me give them
another look.</p>

<p>When I realized that a web worker loaded an entirely separate script resource I almost gave up,
but we’re using <a href="https://webpack.github.io/">webpack</a> so it’s just another entry, right? Kind of. My first attempt
was exactly that which was adding another entry with all my web workin code. The problem with
that is this other script runs in a completely different thread outside of your page so when it
tries to load it has no idea about the webpack module loading. In other words, it didn’t work.</p>

<p>I thought to myself…surely someone has done this before with webpack so off to
<a href="https://lmddgtfy.net/?q=webpack%20web%20worker">duckduckgo</a> it was.
It turns out that there is an
<a href="https://github.com/webpack/webpack/tree/master/examples/web-worker">example</a> of how to do this in
the webpack repo itself. Unfortunately, there’s not a lot of actual words in this example so you have
to have both a good understanding of web workers and webpack to interpret it. The result is going to
be a little anti-climatic since my solution looks a lot like the example, but here goes:</p>

<p>My first step was to make the calculator code where I had previously had the <code class="language-plaintext highlighter-rouge">setTimeout</code>s synchronous:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">calculate</span><span class="p">(</span><span class="nx">years</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">results</span> <span class="o">=</span> <span class="p">{};</span>
  <span class="nx">years</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">year</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">doAllTheThingsForYear</span><span class="p">(</span><span class="nx">year</span><span class="p">,</span> <span class="nx">results</span><span class="p">));</span>
  <span class="k">return</span> <span class="nx">results</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Simple enough, I like deleting code. Step 2 was to change the way I was calling the calculator since
it moved from callback based to synchronous:</p>

<p>Before:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">serviceUsedByComponent</span><span class="p">(</span><span class="nx">$q</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">{</span>
    <span class="na">calculate</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">$q</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">calculatorService</span><span class="p">.</span><span class="nx">calculate</span><span class="p">([</span><span class="mi">2016</span><span class="p">,</span> <span class="mi">2017</span><span class="p">,</span> <span class="mi">2018</span><span class="p">],</span> <span class="p">(</span><span class="nx">results</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">resolve</span><span class="p">(</span><span class="nx">results</span><span class="p">));</span>
      <span class="p">});</span>
    <span class="p">}</span>
  <span class="p">};</span>
<span class="p">}</span>
</code></pre></div></div>

<p>After:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">serviceUsedByComponent</span><span class="p">(</span><span class="nx">$q</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">{</span>
    <span class="na">calculate</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">$q</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">resolve</span><span class="p">(</span><span class="nx">calculatorService</span><span class="p">.</span><span class="nx">calculate</span><span class="p">([</span><span class="mi">2016</span><span class="p">,</span> <span class="mi">2017</span><span class="p">,</span> <span class="mi">2018</span><span class="p">]));</span>
      <span class="p">});</span>
    <span class="p">}</span>
  <span class="p">};</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">$q</code> is Angular’s promise library. I had previously wrapped my interactions with the calculator
in a promise in order to support the setTimeout solution.</p>

<p>At this point I’m back at square one with my component that needs the data using a synchronous call
into the calculator.</p>

<p><em>[webpack enters stage right]</em></p>

<h4 id="making-the-worker-work">making the worker work</h4>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">serviceUsedByComponent</span><span class="p">(</span><span class="nx">$q</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">Worker</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">worker!../workers/calculator.worker</span><span class="dl">'</span><span class="p">);</span>
  <span class="kd">const</span> <span class="nx">worker</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Worker</span><span class="p">();</span>

  <span class="k">return</span> <span class="p">{</span>
    <span class="na">calculate</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">$q</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">worker</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">resolve</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
        <span class="nx">worker</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">([</span><span class="mi">2016</span><span class="p">,</span> <span class="mi">2017</span><span class="p">,</span> <span class="mi">2018</span><span class="p">]);</span>
      <span class="p">});</span>
    <span class="p">}</span>
  <span class="p">};</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Here we change it up a little to instantiate a new worker from the worker code loaded by webpack’s
<a href="https://www.npmjs.com/package/worker-loader">worker-loader</a> so don’t forget to <code class="language-plaintext highlighter-rouge">npm i
worker-loader</code>. Instead of calling the calculator directly we now post a message to the worker
with our calculator input and resolve the promise with the data we get posted back to us from the
worker.  That’s it for calling the worker, now on to the worker itself which is a new file.</p>

<h4 id="working-on-the-worker">working on the worker</h4>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">babel-polyfill</span><span class="dl">'</span><span class="p">);</span>

<span class="kd">const</span> <span class="nx">calculatorService</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">services/calculator.service</span><span class="dl">'</span><span class="p">);</span>

<span class="nx">onmessage</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">postMessage</span><span class="p">(</span><span class="nx">calculatorService</span><span class="p">.</span><span class="nx">calculate</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">));</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The first line imports babels polyfills in case you use anything like <code class="language-plaintext highlighter-rouge">Object.assign</code>. Remember
that this worker is loaded in it’s own thread/context so you don’t get anything from your regular
webpack bundle. The rest of the file is receiving the message we posted from the main thread and posting back
the results of the calculations.</p>

<h4 id="webpackconfigjs">webpack.config.js</h4>

<p>The only thing I changed in my webpack config was taken from the
example itself which sets the output filename for the worker:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">worker</span><span class="p">:</span> <span class="p">{</span>
  <span class="nl">output</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">filename</span><span class="p">:</span> <span class="dl">'</span><span class="s1">calculator.worker.js</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">chunkFilename</span><span class="p">:</span> <span class="dl">'</span><span class="s1">[id].calculator.worker.js</span><span class="dl">'</span>
  <span class="p">}</span>
<span class="p">},</span>
</code></pre></div></div>

<h4 id="ship-it">ship it</h4>

<p>There you have it, webpack saves the day again.</p>

<h4 id="errors">errors</h4>

<p>I left out error handling in my examples for
brevity. I’m starting off with a nodejs style <code class="language-plaintext highlighter-rouge">err</code> property on my postback messages, but it appears
you can get any errors back with an <code class="language-plaintext highlighter-rouge">onerror</code> callback - <a href="http://www.html5rocks.com/en/tutorials/workers/basics/#toc-errors">details here</a>.</p>

<h4 id="browsers">browsers</h4>

<p>Browser support is all I needed it to be, ymmv -
<a href="http://caniuse.com/#feat=webworkers">caniuse</a></p>

<h4 id="performance">performance</h4>

<p>Performance wasn’t any better in my case and it may be slightly worse. I don’t think a user is
going to be able to tell the difference between 500ms and 700ms. The more important part here was
getting these computations off of the ui thread. I’m sending a fairly complex object which may be
helped with <a href="http://www.html5rocks.com/en/tutorials/workers/basics/#toc-transferrables">Transferable
Objects</a>, but I’m calling
it good for now. <code class="language-plaintext highlighter-rouge">¯\_(ツ)_/¯</code></p>

<h4 id="lazy-loading">lazy loading</h4>

<p>An unforeseen benefit in our situation was that this provides lazy loading qualities. Our calculator
is relatively big so it’s nice to not have that in the initial load.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Side Products +]]></title>
      <link href="http://daverupert.com/2015/09/spare-time-product/"/>
    

    
    <updated>2015-09-20T09:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2015/09/20/side-products</id>
    <content type="html"><![CDATA[<blockquote>
  <p>Beyond my woes of ditching Progressive Enhancement for an SPA architecture, I think my biggest takeaway is: Users expect rich interfaces.</p>
</blockquote>

<p><a href="http://twitter.com/davatron5000">Dave Rupert</a> talking about building a side product. Going the full stack rails way is exactly what I would have done (and have done) in the past to build an MVP. My feelings have been starting to shift to API first recently. I think this allows you to iterate more quickly on the client(s) and not be tied to an html producing backend server that you have to meticulously sprinkly javascript on to get the experience that users expect. I’d probably even start with the client first to drive out exactly what is actually needed from the backend. This is what <a href="http://funnelwise.com">my current team</a> did with our product before I started and I think it has worked out well so far.</p>
]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[re-rejecting promises]]></title>
      <link href="https://darrinholst.com/blog/2015/07/28/catching-promises/"/>
    

    
    <updated>2015-07-28T21:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2015/07/28/catching-promises</id>
    <content type="html"><![CDATA[<script async="" src="//assets.codepen.io/assets/embed/ei.js"></script>

<p>Let’s pretend that you have a bit of code like below…</p>

<div data-height="745" data-theme-id="0" data-slug-hash="OVaXmx" data-default-tab="js" data-user="darrinholst" class="codepen">
  <pre>
    <code>
angular.module('demo', [])

  .controller('LoginController', function(loginService) {
    var vm = this;
  
    vm.login = function login() {
      loginService.login(vm.username, vm.password)
        .then(function () {
          setBackground('green');
        })
        .catch(function () {
          setBackground('red');
        });
    }
  
    function setBackground(color) {
      angular.element(document.body).css({'background-color': color});
    }
  })

  .factory('loginService', function ($http, $q) {
    return {
      login: function login(username, password) {
        return $http.post('whatevs', {u: username, p: password})
          .then(function (response) {
            return response.data.token;
          })
          .catch(function (reason) {
            console.log('wtf - ' + reason);
          })
      }
    };
  });
    </code>
  </pre>

  <p>See the Pen <a href="http://codepen.io/darrinholst/pen/OVaXmx/">broken promise</a> by Darrin Holst (<a href="http://codepen.io/darrinholst">@darrinholst</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>

<p>If you’re unfamiliar with angular then the gist of it is that you have 
the <code class="language-plaintext highlighter-rouge">LoginController</code> that gets the <code class="language-plaintext highlighter-rouge">login</code> function called when the Login button is clicked. The controller 
uses a service called <code class="language-plaintext highlighter-rouge">loginService</code> (ignore that part about the service being defined with a <code class="language-plaintext highlighter-rouge">factory</code> call) 
that gets injected via the magical powers of angular. It uses that service to 
call an endpoint and returns a token on success and logs a message on failure. Back in the controller we set the 
background color to green on success and to red on failure. I know, right? That’s web 2.0 at its finest.</p>

<p>Assuming that the http call to <code class="language-plaintext highlighter-rouge">whatevs</code> fails; what do you expect to happen? As of before yesterday my guess would be
the message would get logged in the service and then the controller would set the background to red.</p>

<p>It’d be a pretty boring post if that is what actually happened so go ahead and click Login below to see for yourself.</p>

<p data-height="156" data-theme-id="17343" data-slug-hash="OVaXmx" data-default-tab="result" data-user="darrinholst" class="codepen">See the Pen <a href="http://codepen.io/darrinholst/pen/OVaXmx/">broken promise</a> by Darrin Holst (<a href="http://codepen.io/darrinholst">@darrinholst</a>) on <a href="http://codepen.io">CodePen</a>.</p>

<p>Green, amirite?</p>

<p>We can see from the console that we got the error logged.</p>

<p><img src="/images/re_reject/console.png" alt="console" /></p>

<p>The problem ends up being in our <code class="language-plaintext highlighter-rouge">catch</code> in the service. If you think of it like a traditional try/catch in 
other languages it makes sense. We caught the “exception”, but we didn’t “rethrow” it. The fix is to return 
a rejected promise in our error handling so the rejection gets propagated up the promise chain.</p>

<p>Notice the addition of the <code class="language-plaintext highlighter-rouge">return $q.reject(reason);</code> line in the service ($q is angular’s promise implementation).</p>

<div data-height="747" data-theme-id="17343" data-slug-hash="zGMBJY" data-default-tab="js" data-user="darrinholst" class="codepen">
  <pre>
    <code>
angular.module(&#39;demo&#39;, [])

  .controller(&#39;LoginController&#39;, function(loginService) {
    var vm = this;

    vm.login = function login() {
      loginService.login(vm.username, vm.password)
        .then(function () {
          setBackground(&#39;green&#39;);
        })
        .catch(function () {
          setBackground(&#39;red&#39;);
        });
    }

    function setBackground(color) {
      angular.element(document.body).css({&#39;background-color&#39;: color});
    }
  })

  .factory(&#39;loginService&#39;, function ($http, $q) {
    return {
      login: function login(username, password) {
        return $http.post(&#39;whatevs&#39;, {u: username, p: password})
          .then(function (response) {
            return response.data.token;
          })
          .catch(function (reason) {
            console.log(&#39;wtf - &#39; + reason);
            return $q.reject(reason);
          })
      }
    };
  });
    </code>
  </pre>
  <p>See the Pen <a href="http://codepen.io/darrinholst/pen/zGMBJY/">rejection</a> by Darrin Holst (<a href="http://codepen.io/darrinholst">@darrinholst</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>

<p>Try ‘er again…</p>

<p data-height="159" data-theme-id="17343" data-slug-hash="zGMBJY" data-default-tab="result" data-user="darrinholst" class="codepen">See the Pen <a href="http://codepen.io/darrinholst/pen/zGMBJY/">rejection</a> by Darrin Holst (<a href="http://codepen.io/darrinholst">@darrinholst</a>) on <a href="http://codepen.io">CodePen</a>.</p>

<p>Like most everything else, it makes sense once you know how it works and is completely baffling when you don’t. #themoreyouknow</p>

<p>Check out <a href="http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">this excellent post</a> to get a better understanding of promises if you don’t already know all the things.
 In particular, I found this very helpful…</p>

<blockquote>
  <p>Every promise gives you a then() method (or catch(), which is just sugar for then(null, …)). Here we are inside of a then() function:</p>

  <p>somePromise().then(function () {<br />
    // I’m inside a then() function!<br />
});</p>

  <p>What can we do here? There are three things:</p>

  <ol>
    <li>return another promise</li>
    <li>return a synchronous value (or undefined)</li>
    <li>throw a synchronous error</li>
  </ol>

</blockquote>

<blockquote>
  <p>That’s it. Once you understand this trick, you understand promises.</p>
</blockquote>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[XL stacktraces in your angular tests?]]></title>
      <link href="https://darrinholst.com/blog/2015/05/15/angular-stacktrace/"/>
    

    
    <updated>2015-05-15T21:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2015/05/15/angular-stacktrace</id>
    <content type="html"><![CDATA[<p>I’ve been stumbling through learning angular the last several weeks and I ran into a frustrating problem today where I was getting an excessivly large stacktrace printed in my test output. A contrived example of my test looks like…</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">it</span><span class="p">(</span><span class="dl">'</span><span class="s1">should not have a giant stack trace</span><span class="dl">'</span><span class="p">,</span> <span class="nx">inject</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">$document</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">expect</span><span class="p">(</span><span class="nx">$document</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="dl">'</span><span class="s1">.fumullins</span><span class="dl">'</span><span class="p">)).</span><span class="nx">to</span><span class="p">.</span><span class="nx">have</span><span class="p">.</span><span class="nx">length</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}));</span>
</code></pre></div></div>

<p>Nothing fancy there. It’s just looking to see if an element with a certain class exists on the page. I would expect something like the following to be in the last few lines of my test watch window so I know the test failed for the right reason.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>expected { Object ... } to have a length of 1 but got 0
</code></pre></div></div>

<p>I was presented with the following very helpful output instead…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>the object {
  "line": 875
  "message": "expected { Object (length, prevObject, ...) } to have a length of 1 but got 0"
  "name": "AssertionError"
  "sourceId": 207567360
  "stack": "AssertionError: expected { Object (length, prevObject, ...) } to have a length of 1 but got 0
    at base/node_modules/chai/chai.js?d8de1f708fb0a86a7411a0eba65bb24c852addaa:875
    at assertLength (base/node_modules/chai/chai.js?d8de1f708fb0a86a7411a0eba65bb24c852addaa:1939)
    at base/node_modules/dirty-chai/lib/dirty-chai.js?4ec10c65927a645a87817aa9142cd7df2b9263cb:127
    at base/node_modules/chai/chai.js?d8de1f708fb0a86a7411a0eba65bb24c852addaa:5289
    at assert (base/node_modules/chai/chai.js?d8de1f708fb0a86a7411a0eba65bb24c852addaa:4052)
    at base/spec/app/common/secretFormatter/secretFormatter.directive.spec.js?9dd0fd4d1504a3a1a0b79d0c9533131e13223438:15
    at invoke (base/src/bower_components/angular/angular.js?1061b10c86c20aae22472741139f553995ce2951:4203)
    at workFn (base/src/bower_components/angular-mocks/angular-mocks.js?bd422b0634824fd1aec4b70bdad3b63fc7e1f519:2436)
undefined"
  "stackArray": [
    {
      "line": 875
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/chai/chai.js"
    }
    {
      "function": "assertLength"
      "line": 1939
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/chai/chai.js"
    }
    {
      "line": 127
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/dirty-chai/lib/dirty-chai.js"
    }
    {
      "line": 5289
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/chai/chai.js"
    }
    {
      "function": "assert"
      "line": 4052
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/chai/chai.js"
    }
    {
      "line": 15
      "sourceURL": "/Users/dholst/Projects/secret/spec/app/common/secretFormatter/secretFormatter.directive.spec.js"
    }
    {
      "function": "invoke"
      "line": 4203
      "sourceURL": "/Users/dholst/Projects/secret/src/bower_components/angular/angular.js"
    }
    {
      "function": "workFn"
      "line": 2436
      "sourceURL": "/Users/dholst/Projects/secret/src/bower_components/angular-mocks/angular-mocks.js"
    }
    {
      "function": "callFn"
      "line": 4562
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4555
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4974
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 5079
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "next"
      "line": 4899
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4909
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "next"
      "line": 4844
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4871
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "done"
      "line": 4518
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "callFn"
      "line": 4573
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4555
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "next"
      "line": 4872
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4871
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "done"
      "line": 4518
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "callFn"
      "line": 4573
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4555
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "next"
      "line": 4872
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "line": 4876
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
    {
      "function": "timeslice"
      "line": 6483
      "sourceURL": "/Users/dholst/Projects/secret/node_modules/mocha/mocha.js"
    }
  ]
} was thrown, throw an Error :)
</code></pre></div></div>

<p>Wtf? No, the effing smiley face at the end doesn’t make me feel better, but thanks mocha. That was 138 lines to scroll up to find out that my test failed for the reason I thought it did in case you didn’t count. The good news with modern day javascript development is that there are very few tools in the chain to dig through to figure how to get rid of this giant stackArray thing. Was it karma or was it mocha or was it karma-mocha or maybe chai or possible karma-chai or maybe phantomjs has something to do with it. At this point I was all like (╯°□°）╯︵ ┻━┻.</p>

<p>I was pretty certain that it was a mocha issue and I did find a nice <a href="https://github.com/rstacruz/mocha-clean">stack trace cleaner</a> in the process of trying to figure it out. That helped with the stack, but it didn’t help with that weird stackArray thing.</p>

<p>Some more googling and some greping finally landed me on this in angular-mocks.js…</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span> <span class="p">{</span>
  <span class="nx">injector</span><span class="p">.</span><span class="nx">invoke</span><span class="p">(</span><span class="nx">blockFns</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">||</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">noop</span><span class="p">,</span> <span class="k">this</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">stack</span> <span class="o">&amp;&amp;</span> <span class="nx">errorForStack</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">throw</span> <span class="k">new</span> <span class="nx">ErrorAddingDeclarationLocationStack</span><span class="p">(</span><span class="nx">e</span><span class="p">,</span> <span class="nx">errorForStack</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">throw</span> <span class="nx">e</span><span class="p">;</span>
<span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
  <span class="nx">errorForStack</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">var</span> <span class="nx">ErrorAddingDeclarationLocationStack</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">,</span> <span class="nx">errorForStack</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">this</span><span class="p">.</span><span class="nx">message</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">message</span><span class="p">;</span>
  <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">line</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">line</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">line</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">sourceId</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">sourceId</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">sourceId</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">stack</span> <span class="o">&amp;&amp;</span> <span class="nx">errorForStack</span><span class="p">)</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">stack</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">stack</span> <span class="o">+</span> <span class="dl">'</span><span class="se">\n</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">errorForStack</span><span class="p">.</span><span class="nx">stack</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">stackArray</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">stackArray</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">stackArray</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>This is where the light bulb went off. If you go back up to the test you notice that I wrapped my assertion in an inject call. I did this just out of convenience to get a dependency injected closer to where it was needed in the test.</p>

<h3 id="tldr">tl;dr</h3>

<p>Don’t wrap your assertions in an inject function.</p>

<p>I put my dependencies in a before block like so…</p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">var</span> <span class="vg">$document</span><span class="p">;</span>

<span class="n">beforeEach</span><span class="p">(</span><span class="n">inject</span><span class="p">(</span><span class="n">function</span> <span class="p">(</span><span class="n">_</span><span class="vg">$document_</span><span class="p">)</span> <span class="p">{</span>
  <span class="vg">$document</span> <span class="o">=</span> <span class="n">_</span><span class="vg">$document_</span><span class="p">;</span>
<span class="p">}));</span>

<span class="n">it</span><span class="p">(</span><span class="s1">'should not have a giant stack trace'</span><span class="p">,</span> <span class="n">function</span> <span class="p">()</span> <span class="p">{</span>
  <span class="n">expect</span><span class="p">(</span><span class="vg">$document</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="s1">'.fumullins'</span><span class="p">)).</span><span class="nf">to</span><span class="p">.</span><span class="nf">have</span><span class="p">.</span><span class="nf">length</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">});</span></code></pre></figure>

<p>and #boom, a more sane looking message</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PhantomJS 1.9.8 (Mac OS X) secret-formatter should not have a giant stack trace FAILED
        AssertionError: expected { Object (length, prevObject, ...) } to have a length of 1 but got 0
            at /Users/dholst/Projects/secret/node_modules/chai/chai.js:875
            at assertLength (/Users/dholst/Projects/secret/node_modules/chai/chai.js:1939)
            at /Users/dholst/Projects/secret/node_modules/dirty-chai/lib/dirty-chai.js:127
            at /Users/dholst/Projects/secret/node_modules/chai/chai.js:5289
            at assert (/Users/dholst/Projects/secret/node_modules/chai/chai.js:4052)
            at /Users/dholst/Projects/secret/spec/app/common/secretFormatter/secretFormatter.directive.spec.js:21
</code></pre></div></div>

<p>Hope that helps somebody.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[What Remote Means To Me]]></title>
      <link href="https://darrinholst.com/blog/2014/02/18/remote/"/>
    

    
    <updated>2014-02-18T21:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2014/02/18/remote</id>
    <content type="html"><![CDATA[<p>I have been fortunate enough to work remotely full time for going on 5 months now and I have a few thoughts on it. Most of my thoughts mirror what Jason Fried and DHH said in <a href="http://www.amazon.com/gp/product/B00C0ALZ0W/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B00C0ALZ0W&amp;linkCode=as2&amp;tag=darrinholstco-20">Remote</a>. It’s a really short read that gets to the point much like their other books. I recommend it for not only the person that wants to work remotely, but also for those people that manage remote workers. Management of remote workers plays a big part in the success or failure of it.</p>

<p>Another book I would recommend is <a href="http://www.amazon.com/gp/product/B004J4WNL2/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B004J4WNL2&amp;linkCode=as2&amp;tag=darrinholstco-20">Quiet: The Power of Introverts in a World That Can’t Stop Talking</a>. Although I don’t have any statistics, I think that introverts lean more towards enjoying and thriving in a remote environment. This book is good (and probably better) for the extrovert that doesn’t understand us hermits. I learned a lot about what drives extroverts from reading it.</p>

<p>Remote work is not for every type of person or every type of business, but given the right combination of those two and it can be a satisfying and productive work environment.</p>

<h3 id="the-commute">The Commute</h3>
<p>Remote work means that an hour is not spent in my metal coffin (bonus points if you identify the movie reference Johnny) every day. My math shows 1 hour x 5 days x ~46 weeks x ~40 years = <em>over a calendar year in your car</em>. I would rather use that time getting my <a href="https://www.google.com/search?q=10000+steps">10,000 steps</a> and saving the tremendous amount of money that is sunk into transportation costs. The reduced stress from the lack of a white knuckle drive in a typical Iowa winter is a bonus too. 90% of drivers believe that they are a better than average driver.</p>

<figure class="full">
  <img src="/images/remote/commute.jpg" />
  <figcaption>Hold my beer and watch this shit. WHEEEEEE!</figcaption>
</figure>

<h3 id="family-and-time-management">Family and Time Management</h3>
<p>Working remotely means being able to help get my kids ready for school. It means being able to take them to school when my wife is sick. It means helping my 5 yr old with a puzzle for a few minutes at 10am.</p>

<figure class="full">
  <img src="/images/remote/smurfy.jpg" />
  <figcaption>I don't condone the eating of smurfs. They are calorie dense and nutrient poor.</figcaption>
</figure>

<p>The time I actually do work stays the same, I just get to choose how to slice up my day now. I’m not stuck with 8-12, 1-5 with 2 15 minute smoke breaks.</p>

<h3 id="health-and-nutrition">Health and Nutrition</h3>
<p>Remote means giving a shit about what foods I put into my body and not settling for the usual lunchtime crap. Yes, I’m aware that I can pack a lunch, I’ve tried it…a lot. I’m also aware that it’s a heck of a lot easier to just go upstairs and make something at lunchtime instead of guessing what I’ll want 6 - 18 hours ahead of time. Save money, eat healthier, stay away from people making food for you for the vast majority of your meals.</p>

<figure class="full">
  <img src="/images/remote/lunch.jpg" />
  <figcaption>Lunch is an event. Ask me about intermittent fasting sometime.</figcaption>
</figure>

<h3 id="pajama-time">Pajama Time</h3>
<p>For all the things that remote work means to me, it does not mean <a href="https://twitter.com/Rass30/status/435585349318742016">working in my jammies</a> while watching The Price is Right. I do actually get up at the same time every morning, shower and put on big boy clothes usually beginning around 5:30am. That said, all bets are off at 4pm when Dr. Oz comes on.</p>

<figure class="full">
  <img src="/images/remote/pajamas.jpg" />
  <figcaption>Dr. Oz is going to look sweet on this baby!</figcaption>
</figure>

<p>There is a stigma that is attached to remote workers that we work less. The thing is we know this so that tends to make us work <em>more</em> than we normally would at the office. 40 hours is an important number that shouldn’t be exceeded. Watch out for overwork, it’s as bad or worse than underworking. <a href="https://www.rescuetime.com/dashboard">RescueTime</a> is a good way to keep track of where you spend your time. Give people the tools they need, stimulating things to work on and sit back and watch the human nature to want to do great things work.</p>

<h3 id="carving-out-your-space">Carving Out Your Space</h3>
<p>It also does not mean lounging on the couch with my laptop. I have a dedicated space where I stand roughly 90% of my working day.</p>

<figure class="full">
  <img src="/images/remote/space.jpg" />
  <figcaption>Rustic theme with custom hardwood floors...er desk</figcaption>
</figure>

<p>This is important and it’s one of the reasons remote work failed for me when I tried it over a year ago. I would work from coffee shops or at the kitchen counter or on the couch. Once I setup the space where I work it’s like a switch is flipped in my brain that says ‘I do work stuff here’. I rarely do any personal stuff in my work space which keeps the work/home boundaries more defined.</p>

<h3 id="background-color-transparent">background-color: transparent;</h3>
<p>Transparency is key to a successful remote working environment and more important if you are the minority in your company as a remote worker. Everyone should know what everyone else is working on. I am still working on this piece, but things like hipchat and face to face communication on a regular basis should be incorporated. (Yes, I do get out of the house. How else would I get crickets for the bearded dragon and my Trader Joe’s coconut oil?)</p>

<p>Working remotely has a long way to go to become mainstream (if it ever does) especially in the era that we’re in now where the top of the ladder still believes in the factory worker model. It is changing though and it’s a way of working that I’ve found to be the most sustainable and satisfying for me. All I am saying is <a href="http://www.youtube.com/watch?v=bO2bHSTQvdo#t=28">give remote a chance</a>.</p>

<h3 id="ps">P.S.</h3>
<p>There is a whole other topic that I intentionally skirted. How do Agile practices fit into all of this? I ignored it for now because I haven’t come to a conclusion yet. It may need a <a href="https://signalvnoise.com/posts/3641-rethinking-agile-in-an-office-less-world">rethinking</a>.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Your Largest Organ]]></title>
      <link href="https://darrinholst.com/blog/2013/11/24/your-largest-organ/"/>
    

    
    <updated>2013-11-24T13:45:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2013/11/24/your-largest-organ</id>
    <content type="html"><![CDATA[<p>Ever since I can remember I’ve had skin problems on my hands around this time of year. Problems start with annoying peeling of large chunks of skin and end with cracked, bleeding, and painful hands. I’ve tried countless lotions and medications, but none of them fixed the problem, they just lessened the pain at best. So here I am for a 3-4 week period in the fall with nasty, greasy hands waiting for this year’s episode to pass and thinking ‘that is just what my hands do’.</p>

<p>Enter my latest fad of being health and diet conscious. It started (as far as I can tell) mid-summer with my <a href="http://jawbone.com/store/buy/up">Jawbone UP</a> and making me more mindful of my standard programmer lifestyle. It progressed through calorie counting, getting the <a href="http://www.choosemyplate.gov/">‘proper’</a> ratio of macro-nutrients as determined by our all knowing, ever loving government, <a href="http://www.amazon.com/Good-Calories-Bad-Challenging-Conventional/dp/1400040787">learning that’s all a bunch of crap</a>, the <a href="http://fourhourbody.com/">4 hour body</a> for fat loss, and finally the holy grail of <a href="http://thepaleodiet.com/">paleo</a> and my favorite flavor of paleo: <a href="http://primalblueprint.com/pages/What-We-Do.html">the primal blueprint</a>.</p>

<p>My fad is now nearly 5 months old and is entering the phase where it’s just the way I live. Which brings me back to my hands which are perfectly normal now. I’m about a month past the time that I normally have these problems so I’m calling this one a great success. I’m pretty confident that your diet can fix most of the problems that we encounter today dealing with our bodies. It’s frustrating to believe and experience this while the vast majority of people are oblivious to how important their diet is.</p>

<p>So I’ll just end it with…</p>

<p><img src="/images/organ/womm.png" alt="Works On My Machine" /></p>
]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[CameraSync]]></title>
      <link href="https://darrinholst.com/blog/2013/03/24/camerasync/"/>
    

    
    <updated>2013-03-24T08:30:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2013/03/24/camerasync</id>
    <content type="html"><![CDATA[<p>Ever since my wife decided to dunk our camera into a strawberry daiquiri 2 years ago we have been an iPhone as a primary camera family. Remember back when you used to have an electronic device that it’s primary purpose was to take pictures? The current iPhones are good enough now to be a primary camera for most people which is great for convenience. My problem had always been getting those photos off of the phones and into my library.</p>

<p>My phone was fine since I’d remember to plug it in every week or two and get the pictures off. My wife’s phone was a different story. First, I’d remember to plug it in every couple months. Second, she takes a bunch of photos…some of questionable quality. Combine that with my ocd-like behavior of needing to tag every photo resulted in marathon photo tagging sessions. That sucked.</p>

<p>Then I found a small app called <a href="http://homegrownsw.com/camerasync/">CameraSync</a>.</p>

<p><img src="/images/camera_sync/icon.png" alt="CameraSync" /></p>

<p>CameraSync does what the title says, it syncs your photos to the cloud wirelessly. So I set it up on both phones to sync new photos to a Dropbox folder and now the photos just magically appear on my desktop. Small batches FTW.</p>

<p>But there’s more! CameraSync also does that cool <a href="http://blog.instapaper.com/post/24293729146">background job thing once you enter a geofence</a>. I set it up to sync every time I arrive at my house. So now there is zero interaction with the app, it just does it’s thing by itself.</p>
]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Heroku's Ugly Secret +]]></title>
      <link href="http://rapgenius.com/James-somers-herokus-ugly-secret-lyrics"/>
    

    
    <updated>2013-02-14T08:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2013/02/14/heroku-routing</id>
    <content type="html"><![CDATA[<blockquote>
  <p>In mid-2010, Heroku redesigned its routing mesh so that new requests would be routed, not to the first available dyno, but randomly, regardless of whether a request was in progress at the destination.
<br />
The unfortunate conclusion being that Heroku is not appropriate for any Rails app that’s more than a toy.</p>
</blockquote>

<p>Great analysis of Heroku’s routing.</p>

<p>I love the service that Heroku provides, but I probably wouldn’t put too many of
my eggs in their basket.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[The Riddle of the Gun +]]></title>
      <link href="http://www.samharris.org/blog/item/the-riddle-of-the-gun"/>
    

    
    <updated>2013-01-14T06:52:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2013/01/14/the-riddle-of-the-gun</id>
    <content type="html"><![CDATA[<blockquote>
  <p>As I said at the outset, I do not know how we can solve the problem of gun violence. A renewed ban on “assault weapons”—nearly the only concrete measure that anyone is talking about—will do very little to make our society safer. It is not, as many advocates seem to believe, an important “first step” in achieving a sane policy with respect to guns. It seems likely to be a symbolic step that delays real thinking about the problem of guns for another decade or more. By all means, let us ban these weapons. But when the next lunatic arrives at a school armed with legal pistols and a dozen ten-round magazines, we should be prepared to talk about how an assault weapons ban was a distraction from the real issue of gun violence.</p>
</blockquote>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Installing PostgreSQL 9.1 on Debian 6.0 with Chef]]></title>
      <link href="https://darrinholst.com/blog/2012/12/05/postgres-9-1-on-debian-6-0/"/>
    

    
    <updated>2014-11-08T12:00:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2012/12/05/postgres-9-1-on-debian-6-0</id>
    <content type="html"><![CDATA[<p><strong>11/8/2014 Update:</strong> Ignore all the babbling below and just install it from the <a href="http://www.postgresql.org/about/news/1432/">PGDG repo</a>.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">node</span><span class="p">.</span><span class="nf">set</span><span class="p">[</span><span class="ss">:postgresql</span><span class="p">][</span><span class="ss">:enable_pgdg_apt</span><span class="p">]</span> <span class="o">=</span> <span class="kp">true</span>
<span class="n">node</span><span class="p">.</span><span class="nf">set</span><span class="p">[</span><span class="ss">:postgresql</span><span class="p">][</span><span class="ss">:version</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'9.1'</span>
<span class="n">node</span><span class="p">.</span><span class="nf">from_file</span><span class="p">(</span><span class="n">run_context</span><span class="p">.</span><span class="nf">resolve_attribute</span><span class="p">(</span><span class="s1">'postgresql'</span><span class="p">,</span> <span class="s1">'default'</span><span class="p">))</span>

<span class="n">include_recipe</span> <span class="s1">'postgresql::server'</span>
</code></pre></div></div>

<p>Original content follows…</p>

<p>On a project I’ve been working on I needed to get PostgreSQL
updated from 8.4 to 9.anything on a Debian 6.0 system. 8.4 is the most
up-to-date package on this particular system. Googling around didn’t turn
anything up so this is a documentation of what I did to get it installed
using Chef.</p>

<p>I’m assuming you’re using the <a href="http://community.opscode.com/cookbooks/postgresql">postgresql cookbook</a> and the <a href="http://community.opscode.com/cookbooks/apt">apt cookbook</a>.</p>

<p>One of the first things that you’ll probably run into while searching for a solution is the <a href="http://backports-master.debian.org/">Debian
Backports</a> project. This is a repository of backported packages that will run on an older Debian system. This is where you’ll find packages for PostgreSQL 9.1. You’ll need to add this repository to APT. Add a new file called <code class="language-plaintext highlighter-rouge">cookbooks/postgresql/recipes/squeeze_backports.rb</code> with the following contents</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">apt_repository</span> <span class="s2">"squeeze-backports"</span> <span class="k">do</span>
  <span class="n">uri</span> <span class="s2">"http://backports.debian.org/debian-backports"</span>
  <span class="n">distribution</span> <span class="s2">"squeeze-backports"</span>
  <span class="n">components</span> <span class="p">[</span><span class="s2">"main"</span><span class="p">]</span>
<span class="k">end</span>
</code></pre></div></div>

<p>You could add this recipe everywhere you use <code class="language-plaintext highlighter-rouge">postgresql::server</code> or
<code class="language-plaintext highlighter-rouge">postgresql::client</code>, but I chose to just include it at the top of each of
those recipes</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">include_recipe</span> <span class="s2">"postgresql::squeeze_backports"</span>
</code></pre></div></div>

<p>Now with that repository you can install the packages using the <code class="language-plaintext highlighter-rouge">-t</code> option of
apt-get. Unfortunately I couldn’t find an easy way for the package resource in
chef to do this unobtrusively since it doesn’t look in our backports repository
to figure out what version to install. I did find a <a href="http://tickets.opscode.com/browse/CHEF-1547">bug report</a> in Chef
discussing this and a fix for it, but it wasn’t fixed in the version I was
using. So we’ll do it the DevOps way and hack it…in <code class="language-plaintext highlighter-rouge">cookbooks/postgresql/recipes/client.rb</code> I
replaced:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">node</span><span class="p">[</span><span class="s1">'postgresql'</span><span class="p">][</span><span class="s1">'client'</span><span class="p">][</span><span class="s1">'packages'</span><span class="p">].</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">pg_pack</span><span class="o">|</span>
  <span class="n">package</span> <span class="n">pg_pack</span>
<span class="k">end</span>
</code></pre></div></div>

<p>with:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">execute</span> <span class="s2">"install postgresql-client from backports"</span> <span class="k">do</span>
  <span class="n">command</span> <span class="s2">"apt-get -t squeeze-backports install postgresql-client -y"</span>
  <span class="n">not_if</span> <span class="s2">"dpkg-query -W postgresql-client|grep -q postgresql-client.+"</span>
<span class="k">end</span>

<span class="n">execute</span> <span class="s2">"install libpq-dev from backports"</span> <span class="k">do</span>
  <span class="n">command</span> <span class="s2">"apt-get -t squeeze-backports install libpq-dev -y"</span>
  <span class="n">not_if</span> <span class="s2">"dpkg-query -W libpq-dev|grep -q libpq-dev.+"</span>
<span class="k">end</span>
</code></pre></div></div>

<p>and in <code class="language-plaintext highlighter-rouge">cookbooks/postgresql/server_debian.rb</code> I replaced:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">node</span><span class="p">[</span><span class="s1">'postgresql'</span><span class="p">][</span><span class="s1">'server'</span><span class="p">][</span><span class="s1">'packages'</span><span class="p">].</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">pg_pack</span><span class="o">|</span>
  <span class="n">package</span> <span class="n">pg_pack</span>
<span class="k">end</span>
</code></pre></div></div>

<p>with:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">execute</span> <span class="s2">"install postgresql-server from backports"</span> <span class="k">do</span>
  <span class="n">command</span> <span class="s2">"apt-get -t squeeze-backports install postgresql -y"</span>
  <span class="n">not_if</span> <span class="s2">"dpkg-query -W postgresql|grep -q postgresql.+"</span>
<span class="k">end</span>
</code></pre></div></div>

<p>One last thing you’ll need to do is make sure the PostgreSQL version is set
correctly in <code class="language-plaintext highlighter-rouge">cookbooks/postgresql/attributes/default.rb</code> which just means
removing the check for debian 6.0 so it defaults to 9.1. It ends up looking
something like:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">when</span> <span class="s2">"debian"</span>

  <span class="k">case</span>
  <span class="k">when</span> <span class="n">node</span><span class="p">[</span><span class="s1">'platform_version'</span><span class="p">].</span><span class="nf">to_f</span> <span class="o">&lt;=</span> <span class="mf">5.0</span>
    <span class="n">default</span><span class="p">[</span><span class="s1">'postgresql'</span><span class="p">][</span><span class="s1">'version'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"8.3"</span>
  <span class="k">else</span>
    <span class="n">default</span><span class="p">[</span><span class="s1">'postgresql'</span><span class="p">][</span><span class="s1">'version'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"9.1"</span>
  <span class="k">end</span>
</code></pre></div></div>

<p>Given all of those changes and if all the moons line up then on your next chef client run you
should have version 9.1 installed. Good luck and please add a comment if there
is a more elegant way that I missed.</p>

]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[Regex Golf]]></title>
      <link href="https://darrinholst.com/blog/2012/07/09/regexp-golf/"/>
    

    
    <updated>2012-07-09T21:22:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2012/07/09/regexp-golf</id>
    <content type="html"><![CDATA[<p>I was going to name this post Vim Golf, but it turned out to be more of a regex
experiment than vim keystrokes.</p>

<p>So I found this cool <a href="http://ifttt.com/recipes/37991">ifttt recipe</a> that logs all
of your tweets to a dropbox file. It puts them all in a single file with a
format of:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>At a drive in. Wat?  @ Valle Drive-In http://t.co/Z9lz7O5F
Jun 30, 2012
http://twitter.com/darrinholst/status/218878382123909120
- - - - -

I see blurry apps
Jun 30, 2012
http://twitter.com/darrinholst/status/219074474073538560
- - - - -
</code></pre></div></div>

<p>Since the twitter api only allows you to get to 3200 of your tweets I though it
would be a good idea to get the rest of the tweets that are accessible to me in there as
well. The quickest way I know to get my latest tweets is at
<a href="http://allmytweets.net">allmytweets.net</a>. Allmytweets will pull down all your
tweets and then show them on their page. The html ends up looking like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>8"&gt;&lt;img src="css/extlink.png"&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Straw in the wro
ng hole.  @ High Life Lounge &lt;a href="http://t.co/kdMfTvPk"&gt;
http://t.co/kdMfTvPk&lt;/a&gt; &lt;span class="created_at"&gt;Jun 12, 20
12&lt;/span&gt; &lt;a href="https://twitter.com/#!/darrinholst/status
/212644435689881600"&gt;&lt;img src="css/extlink.png"&gt;&lt;/a&gt;&lt;/li&gt;&lt;li
&gt;I can see @dwolla from here! &lt;span class="created_at"&gt;Jun 1
2, 2012&lt;/span&gt; &lt;a href="https://twitter.com/#!/darrinholst/s
tatus/212639918541910016"&gt;&lt;img src="css/extlink.png"&gt;&lt;/a&gt;&lt;/l
i&gt;&lt;li&gt;Simplify Design With  Zero, One, Many rules &lt;a href="h
ttp://t.co/0bvdVzzo"&gt;http://t.co/0bvdVzzo&lt;/a&gt; &lt;span class="c
</code></pre></div></div>

<p>All the data is there, but not very useful for a txt file. Here’s the commands I threw at it
to format it up:</p>

<p>Split li tags up to separate lines</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&lt;li&gt;/\r&lt;li&gt;/g
</code></pre></div></div>

<p>Preserve new lines in the tweets with a token</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/\n/##NL##/g
</code></pre></div></div>

<p>Change new line tokens in between li tags back to new lines</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&lt;\/li&gt;##NL##&lt;li&gt;/&lt;\/li&gt;\r&lt;li&gt;/g
</code></pre></div></div>

<p>Reverse the order of the tweets, I want them in chronological order (The only
non-replace command)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>g/^/m0
</code></pre></div></div>

<p>Remove li start tags</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&lt;li&gt;//g
</code></pre></div></div>

<p>Replace li end tags with a separator</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&lt;\/li&gt;/\r- - - - -\r/g
</code></pre></div></div>

<p>Turn new line tags back into new lines</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/##NL##/\r/g
</code></pre></div></div>

<p>Get rid of the start span tag for the date</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&lt;span class="created_at"&gt;/\r/g
</code></pre></div></div>

<p>Get rid of the end span tag and tweet link start tag. Also change from https to
http</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&lt;\/span&gt; &lt;a href="https/\rhttp/g
</code></pre></div></div>

<p>Get rid of those stupid #!s</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/\/#!\//\//g
</code></pre></div></div>

<p>Get rid of the image from allmytweets.net</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/"&gt;&lt;img src="css\/extlink.png"&gt;&lt;\/a&gt;//g
</code></pre></div></div>

<p>HTML decode</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&amp;amp;/\&amp;/g
%s/&amp;lt;/&lt;/g
%s/&amp;gt;/&gt;/g
%s/&amp;nbsp;/ /g
</code></pre></div></div>

<p>Get rid of remaining html</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/&lt;a href="//g
%s/"&gt;.*&lt;\/a&gt;//g
</code></pre></div></div>

<p>Clean up trailing spaces</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%s/ *$//g
</code></pre></div></div>

<p>EDITING TEXT IS FUHHHH UHN! I wish I would have though of this 3800 tweets ago
though.</p>
]]></content>
  </entry>
  
  <entry>
    
      <title type="html"><![CDATA[CoffeeScript Function Binding]]></title>
      <link href="https://darrinholst.com/blog/2012/06/08/coffeescript-function-binding/"/>
    

    
    <updated>2012-06-08T06:57:00+00:00</updated>
    
    <id>https://darrinholst.com/blog/2012/06/08/coffeescript-function-binding</id>
    <content type="html"><![CDATA[<p><img src="/images/function_binding/all%20the%20things.jpg" alt="" /></p>

<p>In my last talk that I gave on CoffeeScript I quickly went over function binding and
CoffeeScript’s <code class="language-plaintext highlighter-rouge">=&gt;</code> syntax. My point was that when you need to use <code class="language-plaintext highlighter-rouge">.bind(this)</code> then
you could just use <code class="language-plaintext highlighter-rouge">=&gt;</code> for shorter syntax. The inevitable question that
came up was “Why wouldn’t I just use that everywhere?”. It’s a valid question,
especially coming from people that aren’t in the JavaScript world a lot and/or
haven’t figured out the <code class="language-plaintext highlighter-rouge">this</code> craziness. I didn’t have a good
answer at the time, but I gave the example of jQuery setting <code class="language-plaintext highlighter-rouge">this</code> to the
event element and you might want that <code class="language-plaintext highlighter-rouge">this</code> pointer instead of the current
one.</p>

<div class="language-coffeescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nx">ClickLogger</span>
   <span class="na">clicked</span><span class="o">:</span> <span class="o">-&gt;</span>
     <span class="nx">console</span><span class="p">.</span><span class="na">log</span><span class="p">(</span><span class="err">@</span><span class="p">.</span><span class="na">href</span><span class="p">)</span>

   <span class="na">clickedBound</span><span class="o">:</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=&gt;</span>
     <span class="nx">console</span><span class="p">.</span><span class="na">log</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="na">target</span><span class="p">.</span><span class="na">href</span><span class="p">)</span>

<span class="nx">$</span><span class="p">(</span><span class="s">"a"</span><span class="p">).</span><span class="na">on</span><span class="p">(</span><span class="s">"click"</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ClickLogger</span><span class="p">().</span><span class="na">clicked</span><span class="p">)</span>
<span class="nx">$</span><span class="p">(</span><span class="s">"a"</span><span class="p">).</span><span class="na">on</span><span class="p">(</span><span class="s">"click"</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ClickLogger</span><span class="p">().</span><span class="na">clickedBound</span><span class="p">)</span>
</code></pre></div></div>

<p>In the example above we want the element that was clicked and we don’t need anything from the instance of
<code class="language-plaintext highlighter-rouge">ClickLogger</code> so there is no reason to bind it. It also shows what you would
have to do if you did bind it.</p>

<p>Fast forward to present day when <a href="http://twitter.com/leshill">Les Hill</a> posted
<a href="http://blog.leshill.org/backbone_and_rails_magma">some slides</a> of a Backbone and Rails presentation he did. In there was…</p>

<p><img src="/images/function_binding/warning.jpg" alt="" /></p>

<p>…which got me thinking about it again. So I asked him and his response was…</p>

<p><img src="/images/function_binding/response.jpg" alt="" /></p>

<p>Intention revealing. So by <em>not</em> using <code class="language-plaintext highlighter-rouge">=&gt;</code> everywhere means that I know
what it does and when I should use it and that I really intended to override the
default behavior.</p>

<p>Just because you have shorter syntax to do cumbersome things doesn’t mean you
should use it everywhere, especially if you wouldn’t have naturally done the
cumbersome thing if you didn’t have the shorter syntax.</p>

<p>In case you were wondering if performance was a reason for not using it
everywhere…<a href="http://nesbot.com/2012/1/20/CoffeeScript-why-is-function-binding-not-the-default">it’s not</a>.</p>

]]></content>
  </entry>
  
</feed>
