<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abe Dolinger</title>
    <description>The latest articles on DEV Community by Abe Dolinger (@256hz).</description>
    <link>https://dev.to/256hz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153329%2F23386249-6bce-42ca-9d61-4126bc9caf76.png</url>
      <title>DEV Community: Abe Dolinger</title>
      <link>https://dev.to/256hz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/256hz"/>
    <language>en</language>
    <item>
      <title>DIY VS Code Extension 2: Publish</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Mon, 12 Oct 2020 03:24:59 +0000</pubDate>
      <link>https://dev.to/256hz/diy-vs-code-extension-2-publish-1d00</link>
      <guid>https://dev.to/256hz/diy-vs-code-extension-2-publish-1d00</guid>
      <description>&lt;p&gt;In the last piece, we walked through developing your first VS Code extension.  Congrats!  Now let's put it on the Marketplace.&lt;/p&gt;

&lt;p&gt;A lot of this is covered in &lt;a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension"&gt;Microsoft's guide&lt;/a&gt; - some of which is reproduced here.  I made this because I found some steps a little confusing.&lt;/p&gt;




&lt;h1&gt;
  
  
  Publishing
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Get An Azure Devops Account
&lt;/h2&gt;

&lt;p&gt;In order to manage your extension on the Marketplace, you need an account with Azure Devops.  &lt;a href="https://azure.microsoft.com/en-us/free/devops/"&gt;You can sign up here.&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;(&lt;a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension"&gt;Microsoft's guide&lt;/a&gt; recommends doing this on the command line - this is deprecated.  Do it as below.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/manage"&gt;Head to the Marketplace Management console&lt;/a&gt; to create a publisher.  You'll be asked to enter some info, like the publisher name and ID.&lt;/p&gt;

&lt;p&gt;The publisher ID is what goes into the command string you made in the last step.  Now you can go back and change those, if they are different.  (See &lt;a href="https://dev.to/256hz/diy-vs-code-extension-1-development-1km1#the-command-string"&gt;this section in the last post&lt;/a&gt; for details.  Again, change it everywhere, or nothing will work.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Get the CLI tool
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;npm i -g vsce&lt;/code&gt; (if you're using NPM).  This installs &lt;code&gt;vsce&lt;/code&gt;, the command-line tool we will use to publish the extension.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get a PAT
&lt;/h2&gt;

&lt;p&gt;You'll need a Personal Access Token (PAT).  Head to your DevOps dashboard, which will be here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://dev.azure.com/your-account-name/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token"&gt;Follow the instructions in the official docs&lt;/a&gt; - there are nice screenshots and a thorough walkthrough.&lt;/p&gt;

&lt;p&gt;Remember to extend the life of the token and add the Manage Marketplace scope.&lt;/p&gt;

&lt;p&gt;Copy the token when you see it - if you go back without doing so, you'll lose it and have to start this step over.&lt;/p&gt;




&lt;h2&gt;
  
  
  Log In As Your New Publisher
&lt;/h2&gt;

&lt;p&gt;Run the following on the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vsce login &amp;lt;publisherId&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the publisher ID you created earlier.  The tool will ask for your PAT, which you can paste in here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fill Out Your package.json
&lt;/h2&gt;

&lt;p&gt;Open up your &lt;code&gt;package.json&lt;/code&gt;.  Fill out the following fields.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;name&lt;/code&gt;: the URL slug in the marketplace (format accordingly).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;displayName&lt;/code&gt;: the marketplace title of the extension (what you want people to search for).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;description&lt;/code&gt;: the text that will appear underneath your &lt;code&gt;displayName&lt;/code&gt; in a search.  (The shorter the better.)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;publisher&lt;/code&gt;: the publisher ID you created above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;repository&lt;/code&gt;: the URL of your repo.  It's formatted like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"repository"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/256hz/SwapTernary"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To give your command a default hotkey, you can add &lt;code&gt;contributes.keybindings&lt;/code&gt;.  My &lt;code&gt;contributes&lt;/code&gt; section is below for reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"256hz.swapTernary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Swap Ternary"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"keybindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"256hz.swapTernary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shift+alt+s"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Make A Nice Readme
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;README.md&lt;/code&gt; in the root of your project - this is what will be shown when you browse the extension in the marketplace.  They provide a good template.  It's always nice to have some demo gifs here, usage instructions, and any known issues.&lt;/p&gt;

&lt;p&gt;You can also add a &lt;code&gt;LICENSE&lt;/code&gt; in the root to contain your legal license, and a &lt;code&gt;CHANGELOG.md&lt;/code&gt; for changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Publish!
&lt;/h2&gt;

&lt;p&gt;From the command line, at the root of your extension, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vsce publish 0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use whatever version you like - the script will automatically update your &lt;code&gt;package.json&lt;/code&gt; with the right number.  It does have to be formatted according to the &lt;a href="https://semver.org/"&gt;semVer&lt;/a&gt; rules.&lt;/p&gt;

&lt;p&gt;From here on out, you can forget about the version number if you like.  You can run &lt;code&gt;vsce publish [major/minor/patch]&lt;/code&gt; and it will automatically bump it up for you.&lt;/p&gt;

&lt;p&gt;You should get an email shortly (to the address you added when you created your publisher above).  It should say that the publish was successful and you can now find your extension on the marketplace.&lt;/p&gt;

&lt;p&gt;Give it a shot - open up the Marketplace from VS Code (shift + command + x).  Search for the title you used in your &lt;code&gt;package.json&lt;/code&gt;.  You (and everybody else) can now use your extension!  Time for a PINEAPPLE PARTY.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://unsplash.com/photos/qWlkCwBnwOE"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KKdbYFru--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1496843916299-590492c751f4%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1651%26q%3D80" alt="Pineapple party by Scott Webb Photography" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations, and welcome to the world of extension development.  Have fun!&lt;/p&gt;

&lt;p&gt;If you have any questions or get stuck please feel free to ask below.&lt;/p&gt;




&lt;p&gt;Cover photo: &lt;a href="https://unsplash.com/photos/95YRwf6CNw8"&gt;Code by Clement H on Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>DIY VS Code Extension 1: Development</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Mon, 12 Oct 2020 03:20:48 +0000</pubDate>
      <link>https://dev.to/256hz/diy-vs-code-extension-1-development-1km1</link>
      <guid>https://dev.to/256hz/diy-vs-code-extension-1-development-1km1</guid>
      <description>&lt;p&gt;Have you ever wished for a little extra feature in VS Code, and nothing turns up in a search?  Fear not.  It's time to DIY.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://unsplash.com/photos/t5YUoHW6zRo" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1426927308491-6380b6a9936f%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D2851%26q%3D80" alt="Tools by Barn Images on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few days ago I realized I had once again swapped my true/false cases in a ternary expression.  It's always a little annoying to reformat it, switch the punctuation, redo whitespace, etc.  So I made &lt;a href="https://marketplace.visualstudio.com/items?itemName=256hz.swap-ternary" rel="noopener noreferrer"&gt;&lt;code&gt;SwapTernary&lt;/code&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you want to try it out, it's &lt;a href="https://marketplace.visualstudio.com/items?itemName=256hz.swap-ternary" rel="noopener noreferrer"&gt;here&lt;/a&gt; - or search the VS Code Extension Marketplace for &lt;code&gt;SwapTernary&lt;/code&gt;.  You can also &lt;a href="https://github.com/256hz/SwapTernary" rel="noopener noreferrer"&gt;check out the repo&lt;/a&gt; if you just want to see the code.&lt;/p&gt;

&lt;p&gt;By my calculations, if I save only 11,000 developers just five seconds each, it will be worth the time investment!  Demos below.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fj.gifs.com%2FoV5V2L.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fj.gifs.com%2FoV5V2L.gif" alt="preserves formatting"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fj.gifs.com%2FJyoyZK.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fj.gifs.com%2FJyoyZK.gif" alt="supports nested ternaries (not that you should)"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Development
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Fortunately for us, the VS Code team has made bootstrapping a project a pretty quick process.  One thing I will say for Microsoft is that their push towards better documentation really shines in some areas.  This is one of them.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Please Stop Working With ICE
&lt;/h3&gt;

&lt;p&gt;A much larger thing I will say against Microsoft - &lt;a href="https://www.vox.com/recode/2019/10/9/20906605/github-ice-contract-immigration-ice-dan-friedman" rel="noopener noreferrer"&gt;stop working with ICE&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started, cont'd
&lt;/h2&gt;

&lt;p&gt;Their doc &lt;a href="https://code.visualstudio.com/api/get-started/your-first-extension" rel="noopener noreferrer"&gt;Your First Extension&lt;/a&gt; was hugely helpful, and I recommend following it closely.  I'll cover the essentials here.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://unsplash.com/photos/x7gz40Z9ObM" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1511283402428-355853756676%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1650%26q%3D80" alt="Boots by Oziel Gomez on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Bootstrap Your Extension
&lt;/h2&gt;

&lt;p&gt;The team have made an NPM package using &lt;a href="https://yeoman.io/" rel="noopener noreferrer"&gt;yeoman&lt;/a&gt; that generates a Hello World extension for you, complete with tests.  You can install it with the following command in Terminal (assuming you use NPM):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; yo generator-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When that's all set, run &lt;code&gt;yo code&lt;/code&gt; from the folder you'd like to have your code in.  It offers a nice selection of starter templates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ New Extension (TypeScript) 
  New Extension (JavaScript) 
  New Color Theme 
  New Language Support 
  New Code Snippets 
  New Keymap 
  New Extension Pack 
  New Language Pack (Localization) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I chose the first option.  You'll also be able to enter a name, description, initialize a repo, etc. (Hit Enter to go with defaults - you can always change stuff later.)&lt;/p&gt;

&lt;p&gt;Once that finishes installing, open up &lt;code&gt;src/extension.ts&lt;/code&gt; in Code.  Hit F5 to start the debugger.  A new Code window with your extension installed should appear.&lt;/p&gt;

&lt;p&gt;Then you can enter the Command Palette (Mac: ⇧⌘P, Windows: ^⇧P) and type Hello World, or whatever you named it in the last step.  You should be able to hit Enter and see a friendly popup.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://unsplash.com/photos/N3o-leQyFsI" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1515787366009-7cbdd2dc587b%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1650%26q%3D80" alt="Editing by Kelly Sicema on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Write Some Code
&lt;/h2&gt;

&lt;p&gt;To swap a ternary, I knew I would need to edit selected text.  The team have graciously compiled a &lt;a href="https://github.com/microsoft/vscode-extension-samples" rel="noopener noreferrer"&gt;repo with ~50 sample extensions&lt;/a&gt; for us to work from.  How about &lt;code&gt;document-editing-sample&lt;/code&gt;?  That seems promising.  For me, it's perfect - an extension that reverses the selected text.  The whole thing is below for reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// extension.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExtensionContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disposable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;extension.reverseWord&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the active text editor&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeTextEditor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c1"&gt;// Get the word within the selection&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reversed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editBuilder&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;editBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a lot of useful info here.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your extension must be wrapped in a function called &lt;code&gt;activate&lt;/code&gt;, which takes the editor context as an argument.&lt;/li&gt;
&lt;li&gt;Your code must be registered by the &lt;code&gt;registerCommand&lt;/code&gt; command and stored as a variable.&lt;/li&gt;
&lt;li&gt;That variable must be pushed to the &lt;code&gt;context.subscriptions&lt;/code&gt; array, which where VS Code manages active extensions.&lt;/li&gt;
&lt;li&gt;You already have all this boilerplate in your new extension.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;registerCommand&lt;/code&gt; is where we come in.  It takes two arguments: a string and a function.  Let's talk about the string first.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a href="https://unsplash.com/photos/8gWEAAXJjtI" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1525598912003-663126343e1f%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D2850%26q%3D80" alt="Phone by Quino Al on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Command String
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;command string&lt;/em&gt; takes the format of &lt;code&gt;&amp;lt;publisher&amp;gt;.&amp;lt;commandName&amp;gt;&lt;/code&gt;.  Mine is &lt;code&gt;256hz.swapTernary&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The publisher is you.  If you don't have an Azure DevOps account yet, don't change it now; we'll cover creating a publisher in the next post.&lt;/p&gt;

&lt;p&gt;Enter a &lt;code&gt;commandName&lt;/code&gt;.  Use simple, letter-only strings.  Now, add the whole command string into your &lt;code&gt;package.json&lt;/code&gt; twice: under &lt;code&gt;activationEvents&lt;/code&gt; and &lt;code&gt;contributes.commands&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"activationEvents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"onCommand:256hz.swapTernary"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"256hz.swapTernary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Swap Ternary"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure the command string is the same in all three places or nothing will work.  This is especially true if you are like me and change the name of your command 50 times.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;title&lt;/code&gt; field above is the friendly name that will show up in the Command Palette.&lt;/p&gt;

&lt;p&gt;(You can also add a keybinding here.  See &lt;a href="https://github.com/256hz/SwapTernary/blob/main/package.json" rel="noopener noreferrer"&gt;my package.json&lt;/a&gt; for an example.)&lt;/p&gt;




&lt;p&gt;&lt;a href="https://unsplash.com/photos/fteR0e2BzKo" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1542621334-a254cf47733d%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1650%26q%3D80" alt="Blueprints by Sven Mieke on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Custom Function
&lt;/h2&gt;

&lt;p&gt;Now, the &lt;code&gt;fun&lt;/code&gt; part.  Er, the function.  This is the entry point for your command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeTextEditor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us access to the active editor environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our editor context has a &lt;code&gt;document&lt;/code&gt; and a &lt;code&gt;selection&lt;/code&gt;.  Cool.  These are not raw text, by the way - they are instances of the  &lt;code&gt;Document&lt;/code&gt; and &lt;code&gt;Selection&lt;/code&gt; classes.  Each has special methods and properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we get our raw text.  The &lt;code&gt;Selection&lt;/code&gt; contains pointers to its beginning &amp;amp; end positions in the &lt;code&gt;Document&lt;/code&gt;, and the document takes these and gives you what's between them.&lt;/p&gt;

&lt;p&gt;You can perform whatever logic you want on the text now, and all the work in my extension takes place at this step.  In the example, they reverse the text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reversed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we use the active editor's &lt;code&gt;edit&lt;/code&gt; method to replace what we have.  &lt;code&gt;edit&lt;/code&gt; takes a callback and passes in something called the &lt;code&gt;editBuilder&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;      &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editBuilder&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;editBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;editBuilder.replace&lt;/code&gt; takes two arguments: a &lt;code&gt;Selection&lt;/code&gt;, and  our new, raw text.  &lt;code&gt;selection&lt;/code&gt; is already good to go - we destructured it out of the &lt;code&gt;editor&lt;/code&gt; above.  So all you have to do now is process your text and pass it in as the second argument.&lt;/p&gt;

&lt;p&gt;I needed to do a bunch of string manipulation for my extension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;split the statement up into the condition, true/false clauses, and formatting. &lt;/li&gt;
&lt;li&gt;keep track of whether you're in the middle of a string, so the &lt;code&gt;?:&lt;/code&gt; characters won't be wrongly parsed as syntax.&lt;/li&gt;
&lt;li&gt;keep track of nested ternaries, so we only swap the outermost expression.&lt;/li&gt;
&lt;li&gt;show error modals if the expression can't parse properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy to answer questions about those if you're interested, or you can &lt;a href="https://github.com/256hz/SwapTernary" rel="noopener noreferrer"&gt;check out the repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's all for development!  Now, let's publish the extension.  On to part 2.&lt;/p&gt;




&lt;p&gt;Cover photo: &lt;a href="https://unsplash.com/photos/95YRwf6CNw8" rel="noopener noreferrer"&gt;Code by Clement H on Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>My Interviews After Bootcamp: Summaries</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Mon, 30 Sep 2019 17:04:03 +0000</pubDate>
      <link>https://dev.to/256hz/my-interviews-after-bootcamp-summaries-14f</link>
      <guid>https://dev.to/256hz/my-interviews-after-bootcamp-summaries-14f</guid>
      <description>&lt;p&gt;As a followup to my last piece, I want to give a short (anonymized) picture of what my interviews were like while searching for my first position in the field.  I sent in roughly 300 applications in 3 months.  What follows are the experiences I had with companies where I got at least a phone screen (15, or 0.5%).  &lt;/p&gt;

&lt;p&gt;I hope this provides a window into some of the interview processes / questions you'll encounter, and makes you more comfortable with the idea of failure in the job search.  I never totally got the hang of it - I'd still let my ego get bruised with every rejection.  But it did get easier.&lt;/p&gt;

&lt;p&gt;Every one of these - except the two companies I met at my school's career fair - was from an online application or interaction.  I heard from all over that the quickest way in was through connections at meetups &amp;amp; events.  Meetups kill my family time, so after a couple of unsuccessful startup-themed events, I retreated back to my internet comfort zone.  I don't necessarily endorse this, but it did eventually work for me.&lt;/p&gt;

&lt;p&gt;Again, this happened over three months.  The first month was mostly empty, and I started to pick up steam around the end of the second month.  Most of these happened in the final five weeks of my job search.&lt;/p&gt;

&lt;p&gt;The format is:&lt;/p&gt;

&lt;h2&gt;
  
  
  Company industry/specialty
&lt;/h2&gt;

&lt;p&gt;broad # of employees, application method&lt;br&gt;
&lt;strong&gt;Interview type&lt;/strong&gt;: information&lt;/p&gt;




&lt;h2&gt;
  
  
  Education space/video focus
&lt;/h2&gt;

&lt;p&gt;50 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;HR Interview (Phone):&lt;/strong&gt; Why ********; front or backend; do you know or want to know C#&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; did not advance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Social/e-commerce
&lt;/h2&gt;

&lt;p&gt;1000 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;HR Interview (phone)&lt;/strong&gt; - why ********, career trajectory, what's something at work you're proud of&lt;br&gt;
&lt;strong&gt;Tech Interview 1 (video):&lt;/strong&gt; Longest substring with &lt;code&gt;k&lt;/code&gt; unique characters&lt;br&gt;
&lt;strong&gt;Tech interview 2 (video):&lt;/strong&gt; Reverse letter order in a string; refactor that method to be recursive; reverse word order in a string; build a hash class from the ground up.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; did not advance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Autonomous driving
&lt;/h2&gt;

&lt;p&gt;500 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;Tech Interview 1 (phone):&lt;/strong&gt; React: state management, props, data pathways; Redux state management; CSS box model; CSS frameworks (BEM, Semantic, light vs heavyweight); stackable columns.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; did not advance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Internal chat
&lt;/h2&gt;

&lt;p&gt;100 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;HR Interview (phone):&lt;/strong&gt; why ********, career trajectory, have you ever contributed to process/best practices at work&lt;br&gt;
&lt;strong&gt;Tech interview 1 (Zoom):&lt;/strong&gt; React: lifecycle methods, performance improvements, performant component design; role of Redux in app; containers vs. VMs; Javascript: is JS single-threaded; sync vs async; call stack vs. event stack; front or backend.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Did not advance.&lt;/p&gt;




&lt;h2&gt;
  
  
  B2B candidate services
&lt;/h2&gt;

&lt;p&gt;50 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;Dev Interview (video):&lt;/strong&gt; why ********, career trajectory, work style&lt;br&gt;
&lt;strong&gt;Tech interview 1 (video):&lt;/strong&gt; JS trivia (&lt;code&gt;var&lt;/code&gt; vs &lt;code&gt;let&lt;/code&gt;), &lt;code&gt;innerHTML&lt;/code&gt; === bad.&lt;br&gt;
Q1 - Given a &lt;code&gt;.csv&lt;/code&gt; of # of clicks and a domain, give a total of clicks for each level of the domain&lt;br&gt;
I.e. input: &lt;code&gt;[‘90, sports.yahoo.com’, ‘10, news.yahoo.com’]&lt;/code&gt;&lt;br&gt;
Output: &lt;code&gt;{ com: 100, yahoo.com: 100, sports.yahoo.com: 90, news.yahoo.com: 10 }&lt;/code&gt;&lt;br&gt;
Q2 - Given two arrays of strings, return the longest matching streak. &lt;br&gt;
I.e. input: &lt;code&gt;[‘/home’, ‘/store’, ‘/blog’, ‘/contact’], &lt;br&gt;
[‘/store’, ‘/blog’, ‘/home’, ‘/contact’]&lt;/code&gt;&lt;br&gt;
Output: &lt;code&gt;[‘/store’, ‘/blog’]&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Onsite:&lt;/strong&gt; 6 interviews with 9 people.  Behavioral, system design, product design, programming.  Algorithm question: Common ancestor in two tree nodes.  Given an array of objects that represent a binary tree (each object in the format &lt;code&gt;{parent: child}&lt;/code&gt;), construct the tree and find out if two given nodes share an ancestor.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Did not advance.&lt;br&gt;
&lt;strong&gt;Feedback:&lt;/strong&gt; need more production experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  SEM / UX agency
&lt;/h2&gt;

&lt;p&gt;20 employees, matched at school Job Fair&lt;br&gt;
&lt;strong&gt;HR Interview (in-person):&lt;/strong&gt; Front or backend; where do you see yourself going; app demo&lt;br&gt;
&lt;strong&gt;Tech interview 1 (phone):&lt;/strong&gt; Given a Linux path and the &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;..&lt;/code&gt; operators, return a final path. Input: &lt;code&gt;”/etc/usr/../temp/./../../”&lt;/code&gt;, output: &lt;code&gt;”/”&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Onsite:&lt;/strong&gt; 3 interviews with frontend, backend, &amp;amp; lead developer.  First 2 mostly behavioral, with some design questions: how would you slice up this layout, how would you solve this design problem.  3rd: high-level design of a ‘subscription purchase’ feature on an e-commerce platform, frontend &amp;amp; backend; app demo &amp;amp; minor code review.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; No offer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Finance industry
&lt;/h2&gt;

&lt;p&gt;500 employees, matched at school Job Fair&lt;br&gt;
&lt;strong&gt;Tech interview 1 (in-person):&lt;/strong&gt; App demo; front/backend; where do you see yourself going&lt;br&gt;
&lt;strong&gt;Code challenge (take-home):&lt;/strong&gt; Make a command-line executable that takes a &lt;code&gt;.csv&lt;/code&gt; file and an optional date.  &lt;code&gt;.csv&lt;/code&gt; contains investor transactions/shares purchased.  Output JSON of total cash raised, total shares, and ownership of each investor.&lt;br&gt;
&lt;strong&gt;HR Interview:&lt;/strong&gt; why ********, where do you see yourself going&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; did not advance. &lt;br&gt;
&lt;strong&gt;Feedback:&lt;/strong&gt; code challenge doesn't include tests, doesn't validate # of arguments, created own date/error handling instead of using Ruby builtins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Game/social app
&lt;/h2&gt;

&lt;p&gt;100 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;HR Interview&lt;/strong&gt; (phone) - why ********, career trajectory.  I asked if the position was good for a junior developer, interviewer did not know.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Did not advance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Web services
&lt;/h2&gt;

&lt;p&gt;500,000 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;Tech interview 1 (phone):&lt;/strong&gt; Behavioral: tell about a time the status quo wasn’t good enough and what you did to change it.  Internet: What happens when you type an address in the browser bar.  What is SSL and how does it work.  HTML/CSS: Create a mockup of an accordion: box, header, content.  Tag styles vs class styles, when would you use one vs the other.  JS question: given two arrays of objects with ID keys, combine the matching IDs and return a merged array.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Did not advance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Blockchain solutions
&lt;/h2&gt;

&lt;p&gt;1000 employees, applied on Jumpstart&lt;br&gt;
&lt;strong&gt;HR Interview (phone):&lt;/strong&gt; What is your favorite application of blockchain&lt;br&gt;
&lt;strong&gt;Video Interview:&lt;/strong&gt; I missed it. Messed up the time zone.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Did not advance (shockingly).&lt;/p&gt;




&lt;h2&gt;
  
  
  Backend services
&lt;/h2&gt;

&lt;p&gt;500 employees, applied on LinkedIn&lt;br&gt;
&lt;strong&gt;HR Interview (phone):&lt;/strong&gt; Ruby on Rails experience/projects, deployment.&lt;br&gt;
&lt;strong&gt;Onsite Interview:&lt;/strong&gt; Rails: how to break up functions into folders.  Deployment.  ActiveRecord under the hood. React Native: Navigation props. Platform-specific development. &lt;strong&gt;Feedback:&lt;/strong&gt; they wanted someone with more experience, but would contact in ‘a couple of weeks’ when hiring for a junior position.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Withdrew application on offer&lt;/p&gt;




&lt;h2&gt;
  
  
  Frontend agency
&lt;/h2&gt;

&lt;p&gt;20 employees, applied on AngelList&lt;br&gt;
&lt;strong&gt;Behavioral Interview (video):&lt;/strong&gt; Why ********, where do you see yourself, favorite projects, do you consider yourself an entrepreneur&lt;br&gt;
&lt;strong&gt;Code challenge:&lt;/strong&gt; Make and host a color browser to provided spec.  Hew to layout; color cards, detail view, results pagination; color filtering/searching optional.  Made Rails API backend &amp;amp; React frontend, hosted on Heroku/Netlify respectively.  Feedback: good overall, though lacked proper routing.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Withdrew application on offer&lt;/p&gt;




&lt;h2&gt;
  
  
  IoT solutions
&lt;/h2&gt;

&lt;p&gt;50 employees, recruiter initiated&lt;br&gt;
&lt;strong&gt;Tech screen (video):&lt;/strong&gt; Chat with lead developer, React Native, Java, full stack vs frontend, TypeScript&lt;br&gt;
&lt;strong&gt;Code Challenge:&lt;/strong&gt; Use two in-house tools and Node.js to subscribe to a remote feed of numbers and regularly provide an averaged summary. &lt;br&gt;
&lt;strong&gt;Feedback:&lt;/strong&gt; Got ‘pretty far’. Maybe jumped in too quickly without full grasp of details.&lt;br&gt;
&lt;strong&gt;Onsite:&lt;/strong&gt; React Native: Given an array of animal objects with images, descriptions, &amp;amp; endangered status, show a scrolling list of cards built to a visual spec. Behavioral: client relationships, creative process, managing disagreements, learning process.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Offer accepted.&lt;/p&gt;




&lt;h2&gt;
  
  
  App agency
&lt;/h2&gt;

&lt;p&gt;20 employees, recruiter initiated&lt;br&gt;
&lt;strong&gt;Phone screen (recruiter):&lt;/strong&gt; Why an agency, experience, tools used&lt;br&gt;
&lt;strong&gt;Phone screen (CEO):&lt;/strong&gt; Culture fit, remote work, technology enjoyed.  &lt;strong&gt;Feedback:&lt;/strong&gt; worried that I’m green, but willing to do a tech interview.&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Withdrew application on offer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Backend services
&lt;/h2&gt;

&lt;p&gt;100 employees, recruiter initiated&lt;br&gt;
&lt;strong&gt;Phone screen (Tech Prog Mgr):&lt;/strong&gt; There was none, just wanted to schedule an interview.&lt;br&gt;
&lt;strong&gt;Onsite:&lt;/strong&gt; Algos/data structures?&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Withdrew application on offer&lt;/p&gt;




</description>
      <category>interview</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>So, You've Finished Bootcamp. Are You Employable?</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Wed, 18 Sep 2019 22:13:41 +0000</pubDate>
      <link>https://dev.to/256hz/so-you-ve-finished-bootcamp-are-you-employable-1n9l</link>
      <guid>https://dev.to/256hz/so-you-ve-finished-bootcamp-are-you-employable-1n9l</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2For51eryclkxlpqrld9ns.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2For51eryclkxlpqrld9ns.jpg" alt="Brian, from Life of Brian"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So there I was - sweaty, bedraggled, wild-eyed, and proud; after 15 weeks of intensive web development training, I'd done it.  I'd proved - to myself, and maybe even others - that I understood the fundamentals of programming, and gained intermediate fluency in two languages.  I'd deployed apps in two major frameworks, and gotten the hang of their DSLs.  I had over a thousand commits on Github.  I was employable, and would have a job in no time!&lt;/p&gt;

&lt;p&gt;Countless rejections later, I can tell you that in a competitive market this is simply not the case.  However, in the last few weeks, I've been getting much more consistent interest.  I've advanced to second and third rounds with multiple companies, and today I accepted an offer from my first choice.  As far as I can tell, there are a few reasons for this, and I'd like to break them down for you, the new graduate.  (Also, I never would have gotten this far without the bootcamp, so this is in no way intended to be a substitute to the program.  Think of these as strategies to differentiate yourself from other grads who won't put in this effort.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Specialize . . .
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F962jwz2j9v7v52dlktrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F962jwz2j9v7v52dlktrd.png" alt="Be a specialist."&gt;&lt;/a&gt;&lt;br&gt;
If there's any language or framework or tool or anything you've touched so far that was more interesting to you, dive into &lt;em&gt;that&lt;/em&gt;.  I chose frontend, and specifically React/React Native, since I had the most fun with those.  People love to see that you can learn something really well - you can teach skills, but not the drive to really go deep.  Keep everything on your resume and skill list, but lead with your chosen specialty.  I was hired for a frontend role, but had interest from backend roles, and one company said it was because of the aptitude I showed for React.&lt;/p&gt;

&lt;h2&gt;
  
  
  . . . But Also, Try a Different Stack
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flo2771o5bj2ug8varbbh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flo2771o5bj2ug8varbbh.jpg" alt="Pancakes. Photo by Luke Pennystan on Unsplash"&gt;&lt;/a&gt;&lt;br&gt;
I learned Rails &amp;amp; React in school.  I tried MEAN &amp;amp; MERN afterwards to make sure I could apply my training to new technologies.  And although I now harbor a sort of mild distaste for Angular, hello world-ing in these new technologies was not too hard, and it looks great on my resume.  It also reinforces the idea that you learn new things fast, and won't need 9 months of onboarding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Ya Damn Code (and Write Testable Code)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6c31hgjb3g9ofrwj4kcn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6c31hgjb3g9ofrwj4kcn.jpg" alt="You're a scientist now.  Follow proper testing procedures.  Photo by Trust "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Twice I was asked to comment on the lack of testing in my Github repos, and I didn't advance in either interview.  It was also the main reason I didn't pass my first take-home code challenge.  Coincidence?  I think not.&lt;/p&gt;

&lt;p&gt;In school, all of our labs were built around passing automated tests in Rspec or Jest.  Exposure to test-driven development?  Check!  What they didn't teach us was to write the tests ourselves.  Many of us left feeling like it was a blind spot, and a scary one to tackle alone.  You know what?  For intro projects, making some unit tests is dead easy. &lt;/p&gt;

&lt;p&gt;Testing is ubiquitous in the real world, and even if companies aren't testing 50% of their codebase, they want you to feel like they should.  Fortunately, when something is required of a lot of developers, a few will do the heavy lifting so it's easy for the rest of us.  Modern testing tools are designed to require very little effort to learn.&lt;/p&gt;

&lt;p&gt;Learning to write easily testable code is a bit harder.  Go back to one of your bootcamp projects and write exhaustive unit tests for each feature.  Some things will be easy - do your links navigate to the right URLs?  But you will soon find parts of your code that are impossible to test in isolation.  And that, dear reader, is Bad.  &lt;a href="https://www.toptal.com/qa/how-to-write-testable-code-and-why-it-matters" rel="noopener noreferrer"&gt;Learn more from this excellent blog.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Structures and Algorithms (DSAs)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fen7ile6lk0zjindtt709.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fen7ile6lk0zjindtt709.jpg" alt="Math Lady says learn them."&gt;&lt;/a&gt;&lt;br&gt;
It's very likely you'll be asked to solve an algorithm question - a sort of riddle - in your job search.  There's a lot of chatter by devs at all levels that this part of the interview process is broken.  And really, you won't be solving tiny riddles every day.  When I went through the Flatiron School, we barely scratched the surface; however, they are part of a standard CS degree, and knowing DSAs is often cited as the reason CS students are preferred over bootcampers.&lt;/p&gt;

&lt;p&gt;From my perspective, learning DSAs is invaluable - and being able to select the proper one under pressure does prove that knowledge.  It's part of every dev's job not just to make solutions, but to make &lt;em&gt;efficient&lt;/em&gt; solutions, and to &lt;em&gt;make efficient solutions efficiently&lt;/em&gt;.  If you can break any problem into the most effective DSAs, quickly, you'll be able to focus on larger design patterns or solve inefficiencies in the code of other, inferior developers.  You will be a more effective programmer.&lt;/p&gt;

&lt;p&gt;That said, for junior positions, the questions I've gotten have not been too bad.  I worked the &lt;a href="https://leetcode.com/explore/interview/card/top-interview-questions-easy/" rel="noopener noreferrer"&gt;Easy interview track on Leetcode&lt;/a&gt; until I was comfortable that I understood each one, and that covered 90% of the questions I've seen.  The others were from jobs that were probably above junior level.&lt;/p&gt;

&lt;p&gt;See my eye-crossingly intelligent friend Rylan Bauermeister's pieces on: &lt;a href="https://medium.com/swlh/understanding-data-structures-binary-search-trees-a6612daf00dd" rel="noopener noreferrer"&gt;Binary Trees&lt;/a&gt;, &lt;a href="https://medium.com/@rylanbauermeister/understanding-data-structures-linked-lists-9ca06e2a711a" rel="noopener noreferrer"&gt;Linked Lists&lt;/a&gt;.  &lt;a href="https://www.toolsqa.com/data-structures/hash-tables-in-data-structures/" rel="noopener noreferrer"&gt;Also learn to implement a hash class from scratch&lt;/a&gt;.  This came up multiple times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Good At Vanilla
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwtd4osz5id3x2in6bjtf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwtd4osz5id3x2in6bjtf.jpg" alt="Ice cream.  Photo by sheri silver on Unsplash"&gt;&lt;/a&gt;&lt;br&gt;
I'll use the example of CSS.  While in school, I mainly used frameworks like Bootstrap and Semantic to style my projects, because they were quick to deploy and looked fine.  I was caught out on this in an interview early on when I listed stackable columns as a benefit of a heavyweight framework like Semantic.  This revealed I'd never dove into Flexbox at all, and was ignorant of modern CSS capabilities.  &lt;/p&gt;

&lt;p&gt;So, I took a random card-based page from an e-commerce site, and recreated it in React and vanilla CSS.  It took me about three days.  Did you know you can use variables in vanilla CSS?  How about show an even &lt;code&gt;drop-shadow&lt;/code&gt; border on all four sides of a card with one property?  Use &lt;code&gt;calc&lt;/code&gt; to make your sizing dynamic (or anything dynamic, really)?  Well, I do now.  And knowing that I can do it without the help, or load, of a framework has made me more confident as a frontend developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drink From The Source
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6azhh8wn4vrdv5xpiext.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6azhh8wn4vrdv5xpiext.png" alt="Get your face right in there"&gt;&lt;/a&gt;&lt;br&gt;
Take a framework you've gotten comfortable with, and think of a feature that was tricky for you to get working properly.  (It's not super important which one.)  Now open up its Github repo and look at what it's actually doing.  Confirm it by passing it different inputs.  Tinker!  The source code of a widely-used open source framework is pretty likely to have been formatted for readability.  Maybe the feature isn't perfectly documented - contribute to the README!  I promise this will make you more confident.  I had a PR approved on one of the Google Cloud docs and it did wonders for my self-esteem.  (Super nice folks, btw!)&lt;/p&gt;

&lt;p&gt;By the same token, learning about your language's compiler will also make you better.  Example: &lt;a href="https://www.freecodecamp.org/news/javascript-essentials-why-you-should-know-how-the-engine-works-c2cc0d321553/" rel="noopener noreferrer"&gt;creating identical object models in JS can make searching through those objects 7x faster&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At our level, you shouldn't be expected to know framework source code or compilers from back to front.  You should show that you know they're there, and are comfortable thinking in their terms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dreaded Behavioral Questions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fyhwi3llqlmfjnvedoz53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fyhwi3llqlmfjnvedoz53.png" alt="Where's Your Head At?"&gt;&lt;/a&gt;&lt;br&gt;
There's no way around these.  You're going to have to answer a variation of 'So, tell me about a time you disagreed with someone at work' almost every time.  Look up the &lt;a href="https://www.thebalancecareers.com/what-is-the-star-interview-response-technique-2061629" rel="noopener noreferrer"&gt;STAR&lt;/a&gt; or &lt;a href="https://www.ed.ac.uk/reflection/reflectors-toolkit/reflecting-on-experience/carl" rel="noopener noreferrer"&gt;CARL&lt;/a&gt; techniques for answering these questions, write outlines, and practice them.  Rewrite and practice until you can answer concisely and in a way that indicates you (a) are human, (b) can communicate about emotionally charged situations in a productive way, (c) won't be a horrific asshole to work with, and (d) care about getting shit done that benefits the people around you.  That's all they want to know.  That's pretty reasonable, right?  I mean, that's who I would want to work with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Cover Letter &amp;amp; Resume
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjto5u3ehtkdmoxcbvvvz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjto5u3ehtkdmoxcbvvvz.jpg" alt="Yeah, there's a lot of this.  Photo by Steve Johnson on Unsplash"&gt;&lt;/a&gt;&lt;br&gt;
When sending in a cold application, write a cover letter that's about 3 sentences long.  Mention something from the job post, and why you're drawn to it.  As a the geniuses at The Onion once proclaimed, "Student Thanks Professor Who Taught Him To Pretend To Give A Shit."  Don't cyberstalk every employee or memorize every patch note.  They just need to know that you're comfortable making them part of your identity.&lt;/p&gt;

&lt;p&gt;In a short paragraph on your resume, sing your own praises - not just about your coding abilities (which count!), but all the skills you've gleaned from your other life experience.  In professional language, of course.  Anything that can be construed as project management, communication between groups, creative &amp;amp; technical problem solving - these are all instrumental to your new career.  Emphasize these points under past jobs as well.&lt;/p&gt;

&lt;p&gt;Find the nodes in your life that make you look like this was always your ultimate goal and you are going to excel at it.  They are there, I promise.  Graduating from a bootcamp proves you can absorb a lot of information fast!  That can get a recruiter over the hump if you're missing experience in part of the job's tech stack.  I know a developer who did their whole bootcamp in Python, and got hired for a Ruby job right afterward, by emphasizing this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now . . .
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fj3mr3701fnthgwwjqjdj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fj3mr3701fnthgwwjqjdj.jpeg" alt="Go Forth And Conquer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This probably seems like a lot to do.  It is.  It took me about three months.  I was a little all over the place, but if you're better focused than I am, you could probably do each of these in a two-week span or less.  In the scope of an average job search, that's not that bad.  And I think doing some or all of this will do nothing but benefit you.&lt;/p&gt;

&lt;p&gt;Good luck!  I believe in you!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fc370n5f84b4mp9bihd5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fc370n5f84b4mp9bihd5k.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>bootcamp</category>
      <category>career</category>
    </item>
    <item>
      <title>Deploying a Two-Repo App to One Domain on Heroku</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Tue, 23 Jul 2019 03:27:23 +0000</pubDate>
      <link>https://dev.to/256hz/deploying-a-two-repo-app-to-one-domain-on-heroku-2mhl</link>
      <guid>https://dev.to/256hz/deploying-a-two-repo-app-to-one-domain-on-heroku-2mhl</guid>
      <description>&lt;p&gt;So!  You've followed good practices, and kept the frontend and backend of your new web app in separate Github repos.  (This is nice because it modularizes your project, and allows you to, say, swap out your backend without your frontend having to be redeployed.)  Now it's time to showcase your brand new invention.  However, you want to keep your backend exposed, and you want it to look professional, by hosting it on the same domain as your fronted.  How's that going to work?&lt;/p&gt;

&lt;p&gt;The basic theory of this will apply to any hosting, but since Heroku's interface makes this dead simple, we'll use that as an example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Initial Deployment
&lt;/h3&gt;

&lt;p&gt;Deploy both repos to their own Heroku app.  Heroku has an excellent &lt;a href="https://devcenter.heroku.com/articles/git"&gt;guide&lt;/a&gt; to deploying from Git from the command line, as well as one for deploying from Docker.  It doesn't matter what &lt;code&gt;.herokuapp&lt;/code&gt; domains you choose for them at this point, since they'll only be visible to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Get thee a domain
&lt;/h3&gt;

&lt;p&gt;Get a domain.  There are many registrar choices, and most of them are GoDaddy.  Namecheap and Domain.com also come up a lot as recommended.  YMMV, DYOR.  &lt;strong&gt;Important:&lt;/strong&gt; make sure your choice supports adding custom DNS, specifically CNAME records.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Generate Custom DNS Pointers On Heroku
&lt;/h3&gt;

&lt;p&gt;Now for the fun, and surprisingly easy, part.  Go to your backend's Heroku dashboard.  Open up the Settings tab, and scroll down to Domains and Certificates.  Click the big purple Add Domain button.  This opens the following dialog:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q9fx0w7xma222hx63vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q9fx0w7xma222hx63vn.png" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, type in a subdomain of the domain you own, for example  &lt;code&gt;backend.yourdomain.com&lt;/code&gt;.  It's important that it's a subdomain and not the root: CNAME records can only point to subdomains.&lt;/p&gt;

&lt;p&gt;Heroku auto-generates a unique DNS target; copy this to your clipboard.  After generating, your Domains section will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoysmw749u9zcvrgv5lc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoysmw749u9zcvrgv5lc.png" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(I redacted my DNS targets, but that's where yours will be.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Point your new domain's DNS to those records
&lt;/h3&gt;

&lt;p&gt;Head to your domain's settings page, and look for a DNS area.  In my hosting, it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqqy6wjw8gqfffjsf197.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqqy6wjw8gqfffjsf197.png" width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you're in the DNS panel of your domain, you should see an area to add custom DNS records.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpkv06eadigcy8jw7rx3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpkv06eadigcy8jw7rx3a.png" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how you should fill yours in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ig99sqxip7mgw8c6s1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ig99sqxip7mgw8c6s1d.png" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure the &lt;code&gt;Name&lt;/code&gt; field matches the subdomain of the DNS record you generated on Heroku.  &lt;code&gt;Type&lt;/code&gt; should be CNAME.  The &lt;code&gt;Value&lt;/code&gt; is the one in your clipboard, the long auto-generated DNS pointer address.  Click Add Record and you'll be good to go!&lt;/p&gt;

&lt;p&gt;If you're not curious about CNAMEs, you can skip the next section.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Intermission: A brief diversion on DNS and CNAME records
&lt;/h3&gt;

&lt;p&gt;DNS exists to convert clumsy human things like letters and unicode into the lovely, clean numbers of true IP addresses.  These records exist on many servers around the world, and are cached by your ISP for quicker lookup time.&lt;/p&gt;

&lt;p&gt;Unfortunately, CNAMEs are confusingly - perhaps even badly - named.  CNAME stands for &lt;code&gt;Canonical NAME&lt;/code&gt;.  The implication is that you're changing the 'canonical name' of the record that points to your site's IP address.  &lt;em&gt;It's actually the opposite&lt;/em&gt; - you're creating an &lt;em&gt;alias&lt;/em&gt; to your site's Canonical NAME.  Oh well.  There are rumblings in the DNS community that indicate CNAMEs may eventually be replaced by ANAMEs, the &lt;em&gt;accurately named&lt;/em&gt; &lt;code&gt;Alias NAME&lt;/code&gt; record.  Besides being a properly constructed title, an ANAME is inherently faster than a CNAME: it serves the IP in one query, rather than a CNAME's two.  If only for the sake of naming conventions, I hope that this becomes the standard.  &lt;/p&gt;

&lt;p&gt;Anyway, for now, you're almost certainly stuck with CNAMEs, as there is no formal ANAME standard and very few hosts offer it, and if they do it's going to be their own interpretation.  So it goes.  Intermission is over, let's get back to our program.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Now do it again
&lt;/h3&gt;

&lt;p&gt;Repeat Steps 3 and 4 for your frontend.  Do not repeat step 5, as this would trigger an infinite loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Wait
&lt;/h3&gt;

&lt;p&gt;If you read the DNS section above, you'll remember that DNS records exist in a ton of different places, and are cached under many different schemes.  This is frankly amazing and wonderful, but for you, it means giving DNS a second to catch up with your changes.  I found my CNAME changes happened pretty quickly - within a few minutes - but some changes can take hours, or even a day or two.  With any luck, your experience will be like mine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: The Final Touch
&lt;/h3&gt;

&lt;p&gt;Let's say you want the visitor to experience only having to type in the root domain to get to your project.  That's pretty reasonable.  You're in luck!  Simply forward your root domain to your front-end subdomain.  In my hosting, that's simply called a 'redirect'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhimjg4eeusu6589mphf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhimjg4eeusu6589mphf.png" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should also not take too long.&lt;/p&gt;

&lt;p&gt;Congratulations!  You're now fully hosted and served under one domain.  Now someone can look at your site and have no hint of all the hard work you've done to get it to this point, which I guess was the idea all along.&lt;/p&gt;

&lt;p&gt;You can see my implementation of this at &lt;a href="http://256hz.com"&gt;256hz.com&lt;/a&gt;, which is redirected to &lt;a href="http://portfolio.256hz.com"&gt;portfolio.256hz.com&lt;/a&gt;, which in turn gets its backend data from &lt;a href="http://pgdb.256hz.com"&gt;pgdb.256hz.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading!  If you have any trouble, leave a comment and I'll do what I can to help.  &lt;/p&gt;

</description>
      <category>heroku</category>
      <category>frontend</category>
      <category>backend</category>
      <category>web</category>
    </item>
    <item>
      <title>Intro to Meditation for Coders</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Tue, 04 Jun 2019 15:41:37 +0000</pubDate>
      <link>https://dev.to/256hz/intro-to-meditation-for-coders-1p6f</link>
      <guid>https://dev.to/256hz/intro-to-meditation-for-coders-1p6f</guid>
      <description>&lt;p&gt;Maybe you’ve noticed meditation’s quietly exploding popularity. The benefits are said to be huge, and the difficulty great. There are many methods, each of its own hardcore sect, or expensive new-agey guru. The pseudoscience around it, and the hard-to-quantify results, have turned off many a rational person - maybe including you.&lt;/p&gt;

&lt;p&gt;I am a big proponent of meditation. My own practice is about eight years old. I think it should be taught in schools from an early age. It has the potential to make you feel better and perform better in any situation. No one’s mental health is perfect; meditation is part of any real self-care plan, in my opinion. I’m aiming this post at programmers specifically because coding is a discipline that rewards good mental hygiene. We are required to hold a map of complex interactions, syntax, and business logic in our heads; and as we aren't taught how to process difficult emotions, we often have to work through the fog of those.  This can be difficult, or (at worst) impossible.&lt;/p&gt;

&lt;p&gt;Below, I’ll make a three-part appeal to you to give meditation a shot. If you’re skeptical of meditation’s benefits, Part 1 gets in the weeds about some good evidence for its efficacy. Part 2 is on physical preparation for meditation (super important!). If you want to skip to the meditation exercise itself, it’s last, in part 3.&lt;/p&gt;

&lt;h1&gt;
  
  
  Part 1 — Science
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Improvements in cortical thickness&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://advances.sciencemag.org/content/3/10/e1700489"&gt;This study&lt;/a&gt; (n=322; not huge, but significant) is widely cited; the team of neuroscientists looked for — and found — solid connections between meditations of different types and benefits in brain function.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sr7HK6RJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yvf6a7eougexgj0ac0hm.jpeg" alt=""&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Fig 1. Your cortices are gonna get swoll.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This experiment measured relative thickness of the brain’s cortex. (Cortical thickness is associated positively with brain function; it has been found to be a good predictor for IQ, for example&lt;a href="https://www.sciencedaily.com/releases/2014/03/140304141734.htm"&gt;[1]&lt;/a&gt;). Participants practiced three categories of meditation, for three months each. At the end of each period, researchers found cortical thickening in areas of the brain that corresponded to the goal of that particular meditation. Subjects also performed better in cognitive testing after their training. Loosely: those who trained in “presence” meditation improved their attention spans; those who trained in “affect” showed improved emotional intelligence; and those who trained in “perspective” gained, well, perspective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improvements in bodily function&lt;/strong&gt;&lt;br&gt;
Additional studies have measured physical benefits correlated with meditation, as well. &lt;a href="https://www.ncbi.nlm.nih.gov/pubmed/29616846"&gt;This study&lt;/a&gt; associated lower blood pressure in hypertensives who meditated (warning — low sample size). This one (n=60) found significant decrease in blood sugar level in meditating patients with coronary artery disease. &lt;/p&gt;

&lt;p&gt;There are also a bunch of studies correlating meditation practice in schools leading to improvements in behavior and performance.  I’ll add the complete list  I looked at for this article at the bottom.&lt;/p&gt;

&lt;h1&gt;
  
  
  Part 2 — Preparation
&lt;/h1&gt;

&lt;p&gt;In Sanskrit, ‘yoga’ (&lt;a href="https://en.wikipedia.org/wiki/Yoga"&gt;योग&lt;/a&gt;) is a concept encapsulating many forms of meditation. The practice of stretching we in the West call yoga is only one. That is to say, originally, the stretching in yoga was meant as a preparation for meditation. If your body is sore, tense, unrested, badly positioned, or malnourished, it’s harder to get into a meditative state. I won’t go into proper rest and nutrition, but I will cover two easy stretches that help me relax.&lt;/p&gt;

&lt;p&gt;If you spend all day looking at a computer, the places that are most likely to become tense are your neck, shoulders, arms, and lower back. A good way to test bad posture is to see if it's comfortable to hold in a deep breath. If you’re hunched, for example, you’ll feel tightness near your solar plexus.  When your back is straight and your body is aligned, you can breathe more deeply and fully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hand Claspy Shoulder Stretchy Thing&lt;/strong&gt;&lt;br&gt;
I couldn’t find pictures of this or even a name for it, so I may have made it up out of sheer necessity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sit or stand up straight&lt;/li&gt;
&lt;li&gt;Hold your arms straight out&lt;/li&gt;
&lt;li&gt;Hold hands with yourself&lt;/li&gt;
&lt;li&gt;Relax your shoulders and pull your arms apart. Move your head/neck/hands around for maximum stretchage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is easy to do anywhere, and gives me quick relief from tight shoulders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ragdoll Pose&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ugqU0vs8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4uq5p5txsiq8mkdbdet9.jpeg" alt=""&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Fig 2. It's pretty much just bending in half and relaxing.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are a lot of nice things about “ragdoll pose”: it improves circulation to your head, stretches your lower back, and relaxes your neck and shoulders. I like to relax my neck and wiggle my head back and forth.  Try taking a few deep breaths while you’re down there.  &lt;/p&gt;

&lt;p&gt;Everybody's body is different - if you want to learn stretches for other parts of your body, the internet is a great resource.  If you don't have the time or money for a yoga class, there are good free ones on Youtube.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meditation Prep&lt;/strong&gt;&lt;br&gt;
Once you find somewhere relatively peaceful to sit, check your posture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sit so your back is straight-ish and your legs are relaxed.&lt;/li&gt;
&lt;li&gt;Wiggle your head a little and position it so it’s balanced on your neck.&lt;/li&gt;
&lt;li&gt;Relax your hands in your lap.&lt;/li&gt;
&lt;li&gt;Do the same wiggle but this time with your lower back. Move it around and let it come to rest where it feels most balanced.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(You can do these same checks to see if your posture is okay while you’re working. Here's the &lt;a href="https://www.mayoclinic.org/healthy-lifestyle/adult-health/in-depth/office-ergonomics/art-20046169"&gt;Mayo Clinic's guide to an ergonomic computer setup&lt;/a&gt;, for starters.)&lt;/p&gt;

&lt;h1&gt;
  
  
  Part 3 — First Meditation Exercise
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Thanks for sticking with this so far!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As I touched on in the first part, meditation can have many end goals. For your first time, try one that is simply meant to give your conscious mind a little break.&lt;/p&gt;

&lt;p&gt;Contrary to popular belief, you don’t have to “stop thinking” to get benefits from meditation. In fact, you don’t have to do anything at all. The simplest meditation is predicated on surrender: you don’t have control over your brain, and that’s okay. You only have limited control over your body, and that’s okay, too.&lt;/p&gt;

&lt;p&gt;I spent literal years trying to breathe and force myself to feel peaceful.  It did not work for me.  Here’s the exercise that finally pointed me in a productive direction. This is more aligned with the “presence” category from the first study in part 1. You’ll move your concentration from “thought-awareness” (or -unawareness) to “feeling-awareness”.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set a timer for 10 or 15 minutes. This way you won’t have to keep track of the time while you’re meditating. Consider the time ‘blocked out’. Phone on silent, etc.&lt;/li&gt;
&lt;li&gt;Sit down, let your eyelids close &amp;amp; check your posture (see part 2).&lt;/li&gt;
&lt;li&gt;Maintain a regular schedule of mid-deep breaths. Don’t go crazy, but try to breathe more deeply than you would unconsciously.&lt;/li&gt;
&lt;li&gt;Focus on a part of your body. Every time you breathe out, let it relax. (I like to start at the top of my head and go down, to facial muscles, jaw, neck, shoulders.)&lt;/li&gt;
&lt;li&gt;When (not if) you get distracted, don’t worry about it. Move your concentration back to the last part of your body you were working on, or go straight to where you feel the most tension. Maybe you’ll want to stretch out a tense body part. Go ahead, that’s great — it means you’re improving awareness of your body.&lt;/li&gt;
&lt;li&gt;It’s likely that if you do this for long enough, you will start to feel some kind of difficult emotion. I think part of the reason we’re always doing stuff (I’m looking at you, &lt;em&gt;phone&lt;/em&gt;) is to distract from the emotions we’re worried about having to process. That is a huge benefit of meditation — you’re prompted to experience and deal with whatever you’ve been putting off. Feel the emotion as a physical sensation. A lot of them manifest in your chest or abdomen. Maybe you’ll even feel overwhelmed. Excellent work. Keep breathing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bonus goal: if you keep focusing your awareness on a relaxed body part, you might be able to feel it tingling lightly. I think this is a normal sensation that our brains filter out as noise. I found it easiest to feel this in my hands.&lt;/p&gt;

&lt;p&gt;When the timer goes off, you can shake yourself out, and see if you feel any different.  Sometimes the benefits are obvious, and you'll feel clearer and more present immediately.  Other times, your mind will have been racing the whole time you try to meditate, and you won't feel any better.  Don't despair!  I often find, when that happens to me, that the peaceful feeling comes later in the day.  &lt;/p&gt;

&lt;p&gt;After doing it regularly, I notice it when I stop for a day or two: I find my attention wandering; I feel cranky, unfocused, and mentally foggy.  If 15 minutes  a day seems like a lot, consider that you could be trading it for 15 hours of unhappy or suboptimal thinking.  It's worth it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6EurkyI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1mw3rt9ov86hczcd1er9.jpeg" alt=""&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Fig 3. A still from Bojack Horseman, a cartoon for adults who have difficult emotions.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading!&lt;/strong&gt;&lt;br&gt;
If you have your own meditation tips, or if this helps you in any way, please let me know!  If it doesn't, and you still want to try, I'm happy to talk to you about it, and see if I can help.  Good luck (=&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Appendix: List of Studies&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5934947/"&gt;Effect of 6 Months of Meditation on Blood Sugar, Glycosylated Hemoglobin, and Insulin Levels in Patients of Coronary Artery Disease.&lt;/a&gt;&lt;/em&gt; Sinha, S., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/pubmed/29616846"&gt;Specific Transcriptome Changes Associated with Blood Pressure Reduction in Hypertensive Patients After Relaxation Response Training.&lt;/a&gt;&lt;/em&gt; Bhasin, M., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/pubmed/20141305"&gt;Effects of mindfulness-based stress reduction (MBSR) on emotion regulation in social anxiety disorder.&lt;/a&gt;&lt;/em&gt; Goldin, P.R., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://link.springer.com/article/10.1007/s11031-007-9076-7"&gt;Mindfulness meditation and reduced emotional interference on a cognitive task.&lt;/a&gt;&lt;/em&gt; Ortner, Catherine N.M., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://www.scirp.org/reference/ReferencesPapers.aspx?ReferenceID=1652504"&gt;Mindfulness Training for Elementary School Students: The Attention Academy.&lt;/a&gt;&lt;/em&gt; Napoli, M., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3137946/"&gt;The Influence of Concentrative Meditation Training on the Development of Attention Networks during Early Adolescence.&lt;/a&gt;&lt;/em&gt; Baijal, S., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://jhu.pure.elsevier.com/en/publications/school-based-mindfulness-instruction-an-rct-4"&gt;School-based mindfulness instruction: An RCT.&lt;/a&gt;&lt;/em&gt; Sibinga, E., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://onlinelibrary.wiley.com/doi/abs/10.1111/joop.12115"&gt;A low‐dose mindfulness intervention and recovery from work: Effects on psychological detachment, sleep quality, &amp;amp; sleep duration&lt;/a&gt;&lt;/em&gt; Hülsheger, U., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/pubmed/24395196"&gt;Meditation programs for psychological stress and well-being: a systematic review and meta-analysis.&lt;/a&gt;&lt;/em&gt; Goyal, M., et al.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/pubmed/24395196"&gt;The effects of meditation-based interventions on the treatment of fibromyalgia.&lt;/a&gt;&lt;/em&gt; Kozasa, E.H., et al.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>meditation</category>
      <category>programming</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>The Game of Life (in Ruby)</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Thu, 23 May 2019 15:21:03 +0000</pubDate>
      <link>https://dev.to/256hz/the-game-of-life-in-ruby-2p90</link>
      <guid>https://dev.to/256hz/the-game-of-life-in-ruby-2p90</guid>
      <description>&lt;p&gt;Conway’s Game of Life is a popular coding exercise, often used as a way to explore a new language, or a new facet of a language. I’ll give a brief history (though it’s a fun topic, and I’ve provided links at the bottom if you’d like to learn more).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z7QLFwsS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/0/04/John_H_Conway_2005_%2528cropped%2529.jpg" alt="John Conway" width="800" height="667"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Fig 1. John Conway. by Thane Plambeck&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Game stems from the writings of physicist (and polymath) John von Neumann in the 1940s. We know it as it was refined by mathematician John Conway, in the late 1960s. It was intended as a model of single-celled population growth and decline, played out on a two-dimensional grid. &lt;/p&gt;

&lt;h2&gt;Conway’s Rules&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Each cell has eight neighbors.&lt;/li&gt;
&lt;li&gt;The number of neighbors each cell has determines its life or death into the next turn.&lt;/li&gt;
&lt;li&gt;If the cell has: fewer than two neighbors, it will die of loneliness. &lt;/li&gt;
&lt;li&gt;- two or three neighbors, it will live on. &lt;/li&gt;
&lt;li&gt;- four or more, it will die of overcrowding.&lt;/li&gt;
&lt;li&gt;If an empty space has exactly three neighbors, it will become a living cell.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Under these rules, it’s possible to create structures that move, grow, self-replicate, and sustain indefinitely. This little guy is one of the first "discovered" self-replicating structures, called a Glider.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iU7F4SJx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://upload.wikimedia.org/wikipedia/en/4/45/Rules_of_Conway%2527s_game_of_life_-_Glider.gif" alt="Glider" width="224" height="224"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Fig 2. A small and rather adorable glider.  Wikipedia&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can create massively complex and interactive groups with these rules, including (but not limited to) a &lt;a href="https://www.ics.uci.edu/~welling/teaching/271fall09/Turing-Machine-Life.pdf" rel="noopener noreferrer"&gt;Turing-complete programming language&lt;/a&gt;. After creating your version in Ruby, you’ll be able to simulate these yourself!&lt;/p&gt;

&lt;h3&gt;Life, Meet Ruby&lt;/h3&gt;

&lt;p&gt;This is such a fun exercise because it can be created in a wide variety of ways. Ruby is a very good example of an OOPL, so I’ll cover two options: &lt;strong&gt;Cells as Objects&lt;/strong&gt;, and &lt;strong&gt;Board as Object&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;Cells as Objects&lt;/h4&gt;

&lt;p&gt;In an object-oriented language, it’s natural to think of each component as its own class. In pseudocode, you could describe the Cell class like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cell&lt;/span&gt;

&lt;span class="vi"&gt;@position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count_neighbors&lt;/span&gt;
  &lt;span class="no"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;position&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;position&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;position&lt;/span&gt;
      &lt;span class="n"&gt;create_cell&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;destroy_cell&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each cell knows where it is in your grid, and how to check how many other cells are around it. This is a valid solution, but you can imagine that it quickly gets inefficient. Each cell must iterate through every other cell, every time it wants to count its neighbors! This is known as big O(N²) computational time, meaning the number of calculations required for one "turn" is the square of the number of cells in your array. Also, creating cells gets tricky; since we aren’t making objects for empty cells, measuring the right conditions for a new cell isn’t trivial. In boards with millions of cells, our poor, non-quantum computers will become sad.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://i.giphy.com/media/m9EQQDn3ujpio/giphy.gif" alt="exploding computer" width="520" height="310"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Fig 3. Very sad&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;Board as Object&lt;/h4&gt;

&lt;p&gt;Here’s an option that allows you to only iterate over each cell once, and then each square of the board once. The board is an object, storing an array of positions (cells), with two main methods: get_board_size, and check_board.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Board&lt;/span&gt;
&lt;span class="vi"&gt;@cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_board_size&lt;/span&gt;
  &lt;span class="vi"&gt;@cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;
     &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_board&lt;/span&gt;
  &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;check_neighbors&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;neighbors&lt;/span&gt;
         &lt;span class="n"&gt;create_cell&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;destroy_cell&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to only go over each cell once, to get the size of the board. Then you iterate over the whole board to create and destroy cells. This puts you in the realm of O(N) computational time, meaning the number of calculations your program makes will increase linearly with the number of cells on your board.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There’s good reason Game of Life shows up a lot on lists of coding “katas” and exercises; the rules are simple, but the implementation can vary wildly. The two examples I covered here are only two of the object-oriented possibilities — can you think of ways to make the game in a functional programming environment, for example? There are solutions with finite boards; with hexagons instead of squares; or even with their grids on three-dimensional objects.  Check out the gnarly Trefoil Knot life below.&lt;/p&gt;

&lt;p&gt;You can find my functional-ish Python solution below, which adds simple ASCII visualization, and a small list of preset patterns.&lt;/p&gt;

&lt;p&gt;Happy gaming!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ciHZ-sxH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/6/64/Trefoil_knot_conways_game_of_life.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ciHZ-sxH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/6/64/Trefoil_knot_conways_game_of_life.gif" alt="Life on a Trefoil Knot" width="400" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;More Reading&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/256hz/Game-of-Life/tree/master" rel="noopener noreferrer"&gt;Python GoL example&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.conwaylife.com/wiki/Conway%27s_Game_of_Life" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.conwaylife.com/wiki/Category:Patterns" rel="noopener noreferrer"&gt;Game of Life Wiki: Patterns&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.synthtopia.com/content/2009/04/29/game-of-life-music-sequencer/" rel="noopener noreferrer"&gt;Game of Life Music Sequencer&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/jaoSzCfa9OM" rel="noopener noreferrer"&gt;Game of Life made in Minecraft (whoadude.gif)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>life</category>
      <category>oop</category>
    </item>
    <item>
      <title>Scraping Recipes with Nokogiri</title>
      <dc:creator>Abe Dolinger</dc:creator>
      <pubDate>Wed, 15 May 2019 19:34:58 +0000</pubDate>
      <link>https://dev.to/256hz/scraping-recipes-with-nokogiri-29ih</link>
      <guid>https://dev.to/256hz/scraping-recipes-with-nokogiri-29ih</guid>
      <description>&lt;p&gt;I'm working on a project that requires scraping recipes from the front end of a variety of sites.  An incredible journey!  And the friend I made along the way was right beside me all along!  &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;NOKOGIRI.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Most of you probably know Nokogiri as the point in your Ruby on Rails install where you take a break to get a beverage.  (Why is Nokogiri bundled with every flavor of Rails on Earth?  I have no idea.*  It's quite large, and specialized.)  But here you are, already on a first-name basis with a world-class web scraper.  Want to keep tabs on something that doesn't have an RSS feed?  Aggregate content from a whole category of sites?  Amass training data for your latest NLP project?  You've come to the right place.&lt;/p&gt;

&lt;p&gt;Nokogiri comes with tools for scraping three main formats: CSS, HTML, and XML.  I used a combination of the HTML and CSS tools.  If you like Javascript, a Nokogiri object gives you the equivalent of &lt;code&gt;document.querySelectorAll&lt;/code&gt; on documents not your own.  Then you get to add as much Ruby sugar on top as you like.  If that doesn't sound delicious, you are reading the wrong blog post.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pJVcDeyp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.peppercreekfarms.com/images/Ruby%2520Shimmer%2520Sugar.jpg" width="576" height="1024"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;fig 1. Ruby sugar, anyone?&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first thing you'll need is to request a copy of the page.  I used a gem called HTTParty, for which I took the onerous step of adding &lt;code&gt;'gem httparty'&lt;/code&gt; to my gemfile.  Requesting with HTTParty looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lJbSyv4G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fr8abcco28q0rpft6gu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lJbSyv4G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fr8abcco28q0rpft6gu1.png" alt="" width="490" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tricky.  Bear with me here: loading this into a Noko object is kinda gnarly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--On1trwWD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l47rsnn52h56073inu67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--On1trwWD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l47rsnn52h56073inu67.png" alt="" width="880" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh wait, that was incredibly easy.  Just to be clear, we told NG to parse the HTTParty output as HTML, and store it in an instance variable.  Why an instance variable?  Let's take a moment to reflect on our project setup.&lt;/p&gt;

&lt;p&gt;I recommend separating the scraper object from the model (or models) you use to store the results.  In the scraper, you can keep: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scraping methods&lt;/li&gt;
&lt;li&gt;the URL of interest&lt;/li&gt;
&lt;li&gt;your Nokogiri page object&lt;/li&gt;
&lt;li&gt;your scraped "seed data"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then you can use the seed data to generate the result objects in your database.  Keeping these separate means you're not wasting a bunch of database columns in either model, or giving your results methods they'll never use.&lt;/p&gt;

&lt;p&gt;In my scraper DB objects, I kept the Noko page, recipe title, URL, yield/cook time, and arrays of strings for ingredients and instructions.  Since I'm on Postgres, setting up the array attributes was a piece of cake: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;$ rails g migration add_columns_to_scrapers&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and in your new migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:scrapers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;array: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:scrapers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:instructions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;array: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DknY6h6V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://proxy.duckduckgo.com/iu/%3Fu%3Dhttp%253A%252F%252Ffootage.framepool.com%252Fshotimg%252F113591971-piece-of-cake-cake-plate-cake-fork-strawberry-mousse.jpg%26f%3D1" alt="piece of cake" width="480" height="270"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;fig 2. Cake.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you're on another database, you might create join tables for these attributes, which is slightly less fun.  But hey, you're not using Postgres, so . . tough nuts?  Please be advised, I won't be sparing on the food puns.&lt;/p&gt;

&lt;p&gt;Anyway.  Now the fun part: the scraping methods!&lt;/p&gt;

&lt;p&gt;I was worried I'd have to construct monster conditional regex statements to parse ingredients lists.  Fortunately I was working with well-designed commercial apps, with nice unique classnames.  So, I used Nokogiri's CSS method to scrape my data instead.  &lt;/p&gt;

&lt;p&gt;At the point after you capture your page, set a debugger so you can play with the results.  OK, let's see what the whole thing looks like.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@page&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3-d-nNXA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/v8fun6yn2gszby6sz5lg.png" alt="" width="880" height="221"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;fig 3. Send help pls.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Oof.  This is the first "hard-looking" thing we've come across.  It's really not so bad.  What you're seeing is the Nokogiri object version of every single element and sub-element in the page.  This is actually pretty awesome - it means you have very fine control over the results.&lt;/p&gt;

&lt;p&gt;The recipe title was my first target.  So, I opened up Chrome's Inspect Element, and got the class of the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; title.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S5tnbjM6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/x9rz5o5401buenynvp7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S5tnbjM6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/x9rz5o5401buenynvp7j.png" alt="" width="390" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There it is! The conveniently named &lt;code&gt;page-title&lt;/code&gt;. Now we can use the &lt;code&gt;.css&lt;/code&gt; method:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@page.css(".page-title")&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Phew.  Still with me?  We added the &lt;code&gt;.&lt;/code&gt; to &lt;code&gt;.page-title&lt;/code&gt; to tell Nokogiri we want to search for that term as a class name.  Well, it turns out Noko gives us a little more than we want.  Here are the results of that query:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9eTXnR9t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ypoat9f5ote74gmc154y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9eTXnR9t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ypoat9f5ote74gmc154y.png" alt="" width="880" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fortunately, we can use the &lt;code&gt;.text&lt;/code&gt; method on any of these to, well, get the text. This is a lot like using &lt;code&gt;.textContent&lt;/code&gt; in JS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@page.css(".page-title").text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RE_spshb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sio9buimxtv0vrf95bex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RE_spshb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sio9buimxtv0vrf95bex.png" alt="" width="880" height="26"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're getting close!  All we need is Ruby's excellent &lt;code&gt;.strip&lt;/code&gt; method, which gets rid of whitespace and newlines.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@page.css(".page-title").text.strip&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j6A_w4AI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l3rnpiplhbrazqlw204w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j6A_w4AI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l3rnpiplhbrazqlw204w.png" alt="" width="556" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ta-da!  You've just scraper-Hello-Worlded.&lt;/p&gt;

&lt;p&gt;For all you Ruby chainsmokers like me, getting the array of ingredients is a treat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mGhl51kj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n070dspy705dggo6kv4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mGhl51kj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n070dspy705dggo6kv4e.png" alt="" width="496" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is much the same as the above. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;css("li .component-name")&lt;/code&gt; gets back an array of Noko objects, &lt;/li&gt;
&lt;li&gt;which we convert to a long string with &lt;code&gt;.text&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Then we &lt;code&gt;split&lt;/code&gt; on newlines,&lt;/li&gt;
&lt;li&gt;and map &lt;code&gt;strip&lt;/code&gt; onto each item from the split array. (If that syntax looks weird to you, you can write it as &lt;code&gt;.map {|i| i.strip }&lt;/code&gt;.) &lt;/li&gt;
&lt;li&gt;That gives us a few empty strings as well, so we select the non-empties.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5vUf4vQr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/47ivi7zbh297x9nvv86j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5vUf4vQr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/47ivi7zbh297x9nvv86j.png" alt="" width="880" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Win.  Now I had to parse the ingredients strings for amount, measurement, and name.  That is another blog post all its own, though.  For now, enjoy your newfound skillz!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EdxNXTwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://dailypicksandflicks.com/wp-content/uploads/2012/04/mother-of-god-you-graduated-cake.jpg" alt="" width="600" height="440"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;fig 4. Cake.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Thanks for reading.  Let me know if anything needs to be cleared up or expanded on.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;OK, I googled it.  Rails includes Nokogiri because it's a dependency of the test suite &lt;code&gt;rails-dom-testing&lt;/code&gt;, which makes sense I guess, since you're going to want to parse your page for testing.  Grumble grumble.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>javascript</category>
      <category>scraping</category>
    </item>
  </channel>
</rss>
