<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kate Travers</title>
    <description>The latest articles on Forem by Kate Travers (@ktravers).</description>
    <link>https://forem.com/ktravers</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%2F69549%2F2d3214c2-1685-4731-a54b-ead7b61b0e54.png</url>
      <title>Forem: Kate Travers</title>
      <link>https://forem.com/ktravers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ktravers"/>
    <language>en</language>
    <item>
      <title>Recommended Tech Newsletters</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Sun, 24 Jan 2021 22:14:42 +0000</pubDate>
      <link>https://forem.com/ktravers/recommended-tech-newsletters-4b6g</link>
      <guid>https://forem.com/ktravers/recommended-tech-newsletters-4b6g</guid>
      <description>&lt;p&gt;One of my preferred strategies for staying up to date in tech is newsletters. Call me old school, but I love a good email newsletter. A curated list of recommended blog posts, talks, and career opportunities delivered directly to my inbox? Yes please, much appreciated. I'm subscribed to a ton of them, and I've found them immensely helpful for staying on top of things.&lt;/p&gt;

&lt;p&gt;Which isn't to say I read all of them right away (c'mon, I wish I had that kind of time). Most I'll just skim, maybe save a few links to read later, then archive away. Others I archive instantly, leveraging inbox filters to make sure everything's sorted and tagged for easy retrieval later. The result is my own automated archive of helpful resources, stored safely away in my inbox. When I'm researching something new or looking for inspiration, it's the first place I look.&lt;/p&gt;

&lt;p&gt;Below are a few of my favorites. I hope they're as helpful for you as they have been for me. I'm always looking for new recommendations, so be sure to leave your faves in the comments!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;General&lt;/em&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;a href="https://alistapart.com/email-signup/"&gt;A List Apart&lt;/a&gt; from &lt;a href="https://alistapart.com/about/masthead/"&gt;L. Jeffrey Zeldman et al.&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"A List Apart explores the design, development, and meaning of web content, with a special focus on web standards and best practices."&lt;/em&gt; One of the most long-standing, well-respected magazines in the field. An invaluable resource for thoughtful, insightful, and resonant writing. If you're looking to improve your own technical writing, I also recommend their &lt;a href="https://alistapart.com/about/style-guide/"&gt;style guide&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;a href="https://increment.com/about/#newsletter"&gt;Increment&lt;/a&gt; from &lt;a href="https://stripe.com/"&gt;Stripe&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Increment is a print and digital magazine about how teams build and operate software systems at scale."&lt;/em&gt; A glossy newsletter that's also available in &lt;a href="https://store.increment.com/"&gt;print form&lt;/a&gt;. Impeccably crafted in every sense, it offers monthly issues organized around a single them, like "APIs" or "Open Source", with contributions from some of the biggest names in the industry. [&lt;a href="https://increment.com/security/"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;a href="http://www.pointer.io/"&gt;Pointer.io&lt;/a&gt; from &lt;a href="http://www.pointer.io/about-me/"&gt;Suraj Kapoor&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Pointer is a reading club for developers. It's a window into what other current and future CTOs are reading and thinking about. Super high quality engineering-related content, not just trendy topics or link bait."&lt;/em&gt; So incredibly well-curated, I end up reading or saving almost every link in every issue. If I could only subscribe to one tech newsletter, it'd be this one, no joke. [&lt;a href="http://www.pointer.io/archives/a734ed7df3/"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;a href="https://assaf.substack.com/"&gt;Assaf's Weekend Reading&lt;/a&gt; from &lt;a href="https://assaf.substack.com/about"&gt;Assaf Arkin&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Once a week, in your inbox, the top links about software design and development, people and management, culture and technology. A mix of insightful and funny. Goes great with coffee. ☕️"&lt;/em&gt; This one I usually read right away, start to finish, as soon as it lands in my inbox. It's an absolute delight, as promised. I also enjoy that it includes spicy and/or hilarious tweets from the non-obnoxious part of tech Twitter. [&lt;a href="https://assaf.substack.com/p/weekend-reading-battery-down-to-90"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;a href="https://avdi.codes/sigavdi/"&gt;SIGAVDI&lt;/a&gt; from &lt;a href="https://avdi.codes/"&gt;Avdi Grimm&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"...handpicked links to interesting articles, talks, or resources; an update on what I've published lately; and some reflections at the intersection of software and life."&lt;/em&gt; Avdi Grimm's semi-regular newsletter. A nice glimpse into his personal reading/viewing/listening lists, along with some delicious food pics. [&lt;a href="https://avdi.codes/sigavdi-86-fancy-ramen-edition/"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  6. &lt;a href="https://leaddev.com/#block-subscriptionblock"&gt;LeadDev Originals&lt;/a&gt; from &lt;a href="https://leaddev.com/about-leaddev"&gt;LeadDev&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Weekly words and voices on engineering leadership...[with] the latest advice and upcoming events from LeadDev.com to help you lead effective tech teams."&lt;/em&gt; Roundup of articles and upcoming events from LeadDev.com. They run a fantastic conference series, and I've been really impressed with the caliber of their blog content and talks as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Career&lt;/em&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;a href="https://www.diversifytech.co/join/"&gt;Diversify Tech&lt;/a&gt; from &lt;a href="https://twitter.com/venikunche"&gt;Veni Kunche&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Diversify Tech connects underrepresented people in tech to jobs scholarships, events, speaking opportunities and more."&lt;/em&gt; A fantastic resource for job seekers from underrepresented groups. Includes weekly resources and job alerts. [&lt;a href="https://us2.campaign-archive.com/?u=12f105953ac73ecedfa0b5604&amp;amp;id=ce654312a1"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;And for companies, founders, recruiters and allies, don't miss the weekly Business and Ally edition, with articles on diversity and inclusion from diverse voices, candidates from underrepresented groups who are looking for jobs, and opportunities to learn and advocate for diversity in tech. [&lt;a href="https://mailchi.mp/diversifytech/business-ally-edition-35"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;a href="https://www.break-in.tech/#preFooter"&gt;Break In&lt;/a&gt; from &lt;a href="http://sophiedebenedetto.nyc/"&gt;Sophie DeBenedetto&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"...bi-weekly newsletter designed to help you break in to the tech world."&lt;/em&gt; Whenever someone asks me for advice about changing careers into tech, I always point them to &lt;a href="https://www.break-in.tech"&gt;www.break-in.tech&lt;/a&gt;. It's got a fantastic collection of resources on &lt;a href="https://www.break-in.tech/lessons/category/learning+to+code"&gt;learning to code&lt;/a&gt;, &lt;a href="https://www.break-in.tech/lessons/category/interviewing"&gt;interviewing&lt;/a&gt;, and &lt;a href="https://www.break-in.tech/lessons/category/junior+dev"&gt;succeeding as a junior dev&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;a href="https://tinyletter.com/techspeak"&gt;Technically Speaking&lt;/a&gt; from &lt;a href="https://twitter.com/techspeakdigest"&gt;Chiu-Ki Chan and Cate Huston&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Technically Speaking delivers call for proposals (CFPs), speaking tips, and inspirational videos straight to your inbox."&lt;/em&gt; No longer active, but the &lt;a href="https://tinyletter.com/techspeak/archive"&gt;archives&lt;/a&gt; are worth diving into if you're a current or aspiring technical speaker. [&lt;a href="https://tinyletter.com/techspeak/letters/technically-speaking-august-15-2017"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Language-specific&lt;/em&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;a href="https://rubyweekly.com/"&gt;Ruby Weekly&lt;/a&gt; from &lt;a href="https://twitter.com/peterc"&gt;Peter Cooper&lt;/a&gt;, &lt;a href="https://twitter.com/ruprict"&gt;Glenn Goodrich&lt;/a&gt;, and &lt;a href="https://cooperpress.com/"&gt;Cooperpress&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"A free, once–weekly e-mail round-up of Ruby news and articles."&lt;/em&gt; A must-subscribe for any Ruby developer. Includes job postings. [&lt;a href="https://rubyweekly.com/issues/517"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;a href="https://elixirweekly.net/"&gt;Elixir Weekly&lt;/a&gt; from &lt;a href="http://elixirstatus.com/"&gt;@elixirstatus&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Elixir Community News, one email every Thursday."&lt;/em&gt; Modeled after Ruby Weekly. Includes a mix of blog posts, podcast episodes, and project updates. [&lt;a href="https://elixirweekly.net/#latest-issue"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;a href="https://elixir-radar.com/"&gt;Elixir Radar&lt;/a&gt; from &lt;a href="https://medium.com/@hugobarauna"&gt;Hugo Baraúna&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Weekly Elixir Newsletter. Keep updated with what's happening in the Elixir community."&lt;/em&gt; Includes content, news, events, and job postings. [&lt;a href="https://sendy.elixir-radar.com/w/1H5Ub0cFo5UBnaWX89207fDg/J8921cxQ4jeEDmbVKDWh02aw/Yh90xZuZQffMRAs5Pbpppw"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;a href="https://css-weekly.com/"&gt;CSS Weekly&lt;/a&gt; from &lt;a href="https://twitter.com/ZoranJambor"&gt;Zoran Jambor&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Weekly e-mail roundup of css articles, tutorials, experiments and tools"&lt;/em&gt; [&lt;a href="https://css-weekly.com/issue-425/"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;a href="https://csslayout.news/"&gt;CSS Layout News&lt;/a&gt; from &lt;a href="https://rachelandrew.co.uk/"&gt;Rachel Andrew&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"A weekly collection of tutorials, news and information on all things CSS Layout."&lt;/em&gt; [&lt;a href="https://csslayout.news/issues/266#start"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Stack-specific&lt;/em&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;a href="https://tympanus.net/codrops/newsletter/"&gt;Codrops Collective Newsletter&lt;/a&gt; from &lt;a href="https://tympanus.net/codrops/about/"&gt;Codrops&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Collective features the latest news and resources from the web design &amp;amp; web development community."&lt;/em&gt; One of the first tech newsletters I subscribed to and still one of my faves. Consistently high quality, where every link is interesting. Almost exclusively front-end focused. [&lt;a href="https://tympanus.net/codrops/collective/collective-621/"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;a href="https://css-tricks.com/newsletters/"&gt;This Week in Web Design &amp;amp; Development Newsletter&lt;/a&gt; from CSS-Tricks
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"The most interesting and relevant news and information published [this] week both on CSS-Tricks and off."&lt;/em&gt; Don't let the name of the publisher fool you; they cover all things front-end, not just CSS. [&lt;a href="https://css-tricks.com/newsletter/215-the-gaps-in-the-web-platform/"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;a href="https://codepen.io/spark/"&gt;Codepen Spark&lt;/a&gt; from &lt;a href="https://codepen.io"&gt;Codepen&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Round-up of the week's coolest Pens (HTML, CSS, and JS demos from the community). Always super impressive. [&lt;a href="https://codepen.io/spark/197"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;a href="https://uianimationnewsletter.com/"&gt;UI Animation Newsletter&lt;/a&gt; from &lt;a href="http://twitter.com/vlh"&gt;Val Head&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"Keep up-to-date on the best web animation, motion design, and UX resources on the web! Subscribe for a weekly collection of curated tutorials and articles -- plus advice on how to make web animation work for you."&lt;/em&gt; I subscribed to this newsletter while working on a UI animation feature, thinking I'd unsubscribe when it shipped. But that was almost 3 years ago at this point 😄 [&lt;a href="https://us2.campaign-archive.com/?u=6fbaddc8c1fce7588d1a35cb2&amp;amp;id=75f49463d6"&gt;Example issue&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>newsletters</category>
      <category>recommendations</category>
    </item>
    <item>
      <title>Geocoder Dos and Do Nots</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Tue, 21 Jan 2020 19:01:35 +0000</pubDate>
      <link>https://forem.com/ktravers/geocoder-dos-and-do-nots-1pe8</link>
      <guid>https://forem.com/ktravers/geocoder-dos-and-do-nots-1pe8</guid>
      <description>&lt;p&gt;I was working on a Rails project recently where we needed to 1) track the location of fine art delivery trucks and 2) give dispatchers visibility into which trucks were closest to a given location. Perfect use case for the &lt;a href="https://github.com/alexreisner/geocoder"&gt;Ruby &lt;code&gt;geocoder&lt;/code&gt; gem&lt;/a&gt;, right?&lt;/p&gt;

&lt;p&gt;This gem is a long-respected fan favorite in the Ruby community, first &lt;a href="https://github.com/alexreisner/geocoder/releases?after=0.8.7"&gt;released in 2009&lt;/a&gt; and &lt;a href="https://github.com/alexreisner/geocoder/network/dependents?package_id=UGFja2FnZS02MjgyNQ%3D%3D"&gt;used by upwards of 23.5k projects&lt;/a&gt;. However, this was my first time working with it, and I managed to bungle my first implementation. I wanted to share my journey from sad path to happy path, in hopes that it'll help someone else out there, too.&lt;/p&gt;

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

&lt;p&gt;We're starting with the following schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/truck.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;location&lt;/span&gt;
    &lt;span class="c1"&gt;# TODO&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;set_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="c1"&gt;# TODO&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# schema.rb&lt;/span&gt;
&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="mi"&gt;20191008222320&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"trucks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Didn't Work 🙅‍♀️
&lt;/h2&gt;

&lt;p&gt;For my first pass, I opted to create a separate &lt;code&gt;locations&lt;/code&gt; table. The idea was to maintain separation of concerns between &lt;code&gt;trucks&lt;/code&gt; and &lt;code&gt;locations&lt;/code&gt;, keeping them loosely coupled so they'd both be easier to extend (or deprecate, in case this whole truck tracking idea didn't work out).&lt;/p&gt;

&lt;p&gt;I also didn't originally like the idea of tacking &lt;code&gt;latitude&lt;/code&gt; and &lt;code&gt;longitude&lt;/code&gt; on to the existing &lt;code&gt;trucks&lt;/code&gt; table. Those didn't seem like inherit properties of a truck; instead, in my mind, a truck has many locations, current and past. Another bonus of a separate &lt;code&gt;locations&lt;/code&gt; table is that it allows us to keep track of a truck's past locations, which also seemed appealing to me (in case we wanted to recreate a timeline of the truck's movements, for example).&lt;/p&gt;

&lt;p&gt;So with that rationale in mind, I added a &lt;code&gt;locations&lt;/code&gt; table, model, and associations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/location.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Location&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:truck&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/truck.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:locations&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;address&lt;/span&gt;
    &lt;span class="c1"&gt;# TODO&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;location&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
    &lt;span class="n"&gt;most_recent_location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;created_at: :desc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;most_recent_location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_recent_location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&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;set_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;latitude: &lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;longitude: &lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# schema.rb&lt;/span&gt;
&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="mi"&gt;20191008351012&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"trucks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;# same as above&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"truck_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decimal&lt;/span&gt; &lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;scale: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decimal&lt;/span&gt; &lt;span class="s2"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;scale: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"index_locations_on_truck_id"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I checked the &lt;a href="https://github.com/alexreisner/geocoder#geocoding-objects"&gt;geocoder docs&lt;/a&gt;. Per the docs, there's four things necessary to geocode an object:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Provide a method that returns an address to geocode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'd read somewhere it was ok to stub this out to return nil, so I opted to start there, since knowing a truck's address wasn't one of our requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Provide a way to store latitude and longitude coordinates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The docs suggest adding &lt;code&gt;:latitude&lt;/code&gt; and &lt;code&gt;:longitude&lt;/code&gt; attributes to the model you're geocoding (in our case, &lt;code&gt;Truck&lt;/code&gt;), but I figured I could overwrite these by adding methods that hooked into the associated &lt;code&gt;Location&lt;/code&gt; attributes instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Tell geocoder where to find the object's address&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I opted to start with the default examples provided in the docs: &lt;code&gt;geocoded_by :address&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Add &lt;code&gt;after_validation :geocode&lt;/code&gt; to model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;...all of which lead to the following updates to my &lt;code&gt;Truck&lt;/code&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/truck.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:locations&lt;/span&gt;

  &lt;span class="n"&gt;geocoded_by&lt;/span&gt; &lt;span class="ss"&gt;:address&lt;/span&gt;
  &lt;span class="n"&gt;after_validation&lt;/span&gt; &lt;span class="ss"&gt;:geocode&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;address&lt;/span&gt;
    &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;# stubbed, not necessary for our requirements&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;latitude&lt;/span&gt;
    &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:first&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;longitude&lt;/span&gt;
    &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:last&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;location&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
    &lt;span class="n"&gt;most_recent_location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;created_at: :desc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;most_recent_location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_recent_location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&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;set_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;latitude: &lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;longitude: &lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration worked fine in terms of setting and getting location:&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;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
  &lt;span class="no"&gt;Truck&lt;/span&gt; &lt;span class="no"&gt;Load&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="no"&gt;SELECT&lt;/span&gt;  &lt;span class="s2"&gt;"trucks"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"trucks"&lt;/span&gt; &lt;span class="no"&gt;ORDER&lt;/span&gt; &lt;span class="no"&gt;BY&lt;/span&gt; &lt;span class="s2"&gt;"trucks"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="no"&gt;ASC&lt;/span&gt; &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Truck id: 1, name: "Maquette Fine Art Services", created_at: "2019-10-10 04:10:58", updated_at: "2019-10-10 04:10:58"&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;002&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;location&lt;/span&gt;
  &lt;span class="no"&gt;Location&lt;/span&gt; &lt;span class="no"&gt;Exists&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="no"&gt;SELECT&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="no"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;003&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;latitude: &lt;/span&gt;&lt;span class="mf"&gt;37.782267&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;longitude: &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.391248&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;begin&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
  &lt;span class="no"&gt;SQL&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.9&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="no"&gt;INSERT&lt;/span&gt; &lt;span class="no"&gt;INTO&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;?,&lt;/span&gt; &lt;span class="p"&gt;?,&lt;/span&gt; &lt;span class="sc"&gt;?,&lt;/span&gt; &lt;span class="p"&gt;?,&lt;/span&gt; &lt;span class="sc"&gt;?)&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;37.782267&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.391248&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"2019-10-10 04:12:12.953575"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"2019-10-10 04:12:12.953575"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.5&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Location id: 1, truck_id: 1, latitude: 0.37782267e2, longitude: -0.122391248e3, created_at: "2019-10-10 04:12:12", updated_at: "2019-10-10 04:12:12"&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;004&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;location&lt;/span&gt;
  &lt;span class="no"&gt;Location&lt;/span&gt; &lt;span class="no"&gt;Load&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="no"&gt;SELECT&lt;/span&gt;  &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"longitude"&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="no"&gt;ORDER&lt;/span&gt; &lt;span class="no"&gt;BY&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"created_at"&lt;/span&gt; &lt;span class="no"&gt;DESC&lt;/span&gt; &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;37.782267&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;122.391248&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, it broke down immediately when I tried to actually geocode anything:&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;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;005&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;geocode&lt;/span&gt;
  &lt;span class="no"&gt;Location&lt;/span&gt; &lt;span class="no"&gt;Load&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="no"&gt;SELECT&lt;/span&gt;  &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"longitude"&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="no"&gt;ORDER&lt;/span&gt; &lt;span class="no"&gt;BY&lt;/span&gt; &lt;span class="s2"&gt;"locations"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"created_at"&lt;/span&gt; &lt;span class="no"&gt;DESC&lt;/span&gt; &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"truck_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="no"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="no"&gt;NoMethodError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="sb"&gt;`latitude=' for #&amp;lt;Truck:0x00007ff3c2b58098&amp;gt;)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's not really a good workaround for this error. Adding setter methods for &lt;code&gt;Truck#latitude=&lt;/code&gt; and &lt;code&gt;Truck#longitude=&lt;/code&gt; doesn't do the trick, because we don't want to create new &lt;code&gt;Location&lt;/code&gt; records with only one of those attributes filled in. I thought about adding some kind of temp &lt;code&gt;Location&lt;/code&gt; object that'd be persisted after both attributes were filled in, but at that point, the code smell was pretty obvious. It shouldn't be this difficult. I was clearly doing something wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UHFLOf9V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.freeutopia.org/wp-content/uploads/Ive-made-a-huge-mistake.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UHFLOf9V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.freeutopia.org/wp-content/uploads/Ive-made-a-huge-mistake.jpg" alt="Gob Bluth has made a huge mistake" title="Gob Bluth has made a huge mistake" width="387" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Worked 🏄‍♀️
&lt;/h2&gt;

&lt;p&gt;I went back to the &lt;code&gt;geocoder&lt;/code&gt; docs and recognized that &lt;code&gt;latitude&lt;/code&gt; and &lt;code&gt;longitude&lt;/code&gt; attributes had to live on the model I wanted to geocode (&lt;code&gt;Truck&lt;/code&gt;). That's what the library expects, and things start to get gnarly if you try to override that.&lt;/p&gt;

&lt;p&gt;Plus after giving it more thought, there's not much to be gained by separating out these properties into a separate table.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There's no immediate need to keep track of past locations, so no need to make a premature optimization to support it.&lt;/li&gt;
&lt;li&gt;It's just as easy to drop columns as a table, should I want to deprecate this functionality in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that in mind, the next step was to undo the work I did to add &lt;code&gt;locations&lt;/code&gt;, then run a migration to add &lt;code&gt;latitude&lt;/code&gt; and &lt;code&gt;longitude&lt;/code&gt; to &lt;code&gt;trucks&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/truck.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;geocoded_by&lt;/span&gt; &lt;span class="ss"&gt;:address&lt;/span&gt;
  &lt;span class="n"&gt;after_validation&lt;/span&gt; &lt;span class="ss"&gt;:geocode&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;address&lt;/span&gt;
    &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;# stubbed, not necessary for our requirements&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;location&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;longitude&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;set_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;latitude: &lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;longitude: &lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# schema.rb&lt;/span&gt;
&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="mi"&gt;20191008351012&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"trucks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decimal&lt;/span&gt; &lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;scale: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decimal&lt;/span&gt; &lt;span class="s2"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;precision: &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;scale: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To the great suprise of no one, following the docs' recommended implementation allowed me to greatly simplify my code, and -- most importantly -- actually get it working.&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;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;006&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;latitude: &lt;/span&gt;&lt;span class="mf"&gt;37.782267&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;longitude: &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.391248&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;begin&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;007&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;geocoded?&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we can properly geocode our &lt;code&gt;Truck&lt;/code&gt;s, we have access to helpful methods like &lt;code&gt;near&lt;/code&gt; and &lt;code&gt;distance&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nearby_trucks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;near&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;truck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;Truck&lt;/span&gt; &lt;span class="no"&gt;Load&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="no"&gt;SELECT&lt;/span&gt;  &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;69.09332411348201&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;ABS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;37.882267&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.7071067811865475&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="mf"&gt;59.836573914187355&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;ABS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.7071067811865475&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CASE&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt;  &lt;span class="mf"&gt;45.0&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt; &lt;span class="mf"&gt;135.0&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt; &lt;span class="mf"&gt;225.0&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt; &lt;span class="mf"&gt;315.0&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="no"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;bearing&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"trucks"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="no"&gt;BETWEEN&lt;/span&gt; &lt;span class="mf"&gt;37.15860808444576&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="mf"&gt;38.60592591555424&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="no"&gt;BETWEEN&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;123.20811433750569&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;121.37438166249433&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;ORDER&lt;/span&gt; &lt;span class="no"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="no"&gt;ASC&lt;/span&gt; &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;ActiveRecord::Relation [#&amp;lt;Truck id: 1, name: "Maquette Fine Art Services", created_at: "2019-10-13 18:22:51", updated_at: "2019-10-13 18:23:55", latitude: 0.37782267e2, longitude: -0.122391248e3&amp;gt;]&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nearby_trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;
  &lt;span class="no"&gt;Truck&lt;/span&gt; &lt;span class="no"&gt;Load&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="no"&gt;SELECT&lt;/span&gt;  &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;69.09332411348201&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;ABS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;37.882267&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.7071067811865475&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="mf"&gt;59.836573914187355&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;ABS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.7071067811865475&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CASE&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt;  &lt;span class="mf"&gt;45.0&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt; &lt;span class="mf"&gt;135.0&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt; &lt;span class="mf"&gt;225.0&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;37.882267&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.29124800000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;THEN&lt;/span&gt; &lt;span class="mf"&gt;315.0&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="no"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;bearing&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"trucks"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt; &lt;span class="no"&gt;BETWEEN&lt;/span&gt; &lt;span class="mf"&gt;37.15860808444576&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="mf"&gt;38.60592591555424&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;trucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt; &lt;span class="no"&gt;BETWEEN&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;123.20811433750569&lt;/span&gt; &lt;span class="no"&gt;AND&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;121.37438166249433&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;ORDER&lt;/span&gt; &lt;span class="no"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="no"&gt;ASC&lt;/span&gt; &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;9.116720519305336&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;Working with the &lt;code&gt;geocoder&lt;/code&gt; gem for the first time was a good reminder not to over-architect too early, and most importantly, go with what the docs recommend. Especially with an established, widely-used library like &lt;code&gt;geocoder&lt;/code&gt;, you can trust the library authors to steer you in the right direction, especially for straight-forward use cases like mine. Let's hope future Kate remembers this next time she tackles a new library.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.rubygeocoder.com/"&gt;Geocoder gem site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/alexreisner/geocoder"&gt;Geocoder gem source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>geocoder</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Interview Prep: Critical Questions for You and Them</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Tue, 21 Jan 2020 18:52:11 +0000</pubDate>
      <link>https://forem.com/ktravers/interview-prep-critical-questions-for-you-and-them-dd7</link>
      <guid>https://forem.com/ktravers/interview-prep-critical-questions-for-you-and-them-dd7</guid>
      <description>&lt;p&gt;At the end of 2019, I started looking for a new software engineering job, something I hadn't done in almost five years. I'd been very involved with my previous company's hiring process, helping design our interview process and running dozens of interviews for engineering and product team candidates at every level and role, so I thought was ready to be on the other side of the table.&lt;/p&gt;

&lt;p&gt;Welp, surprise surprise, turns out I was super rusty. After floundering through my first couple behavioral interviews, I realized I couldn't go into these things cold. I needed to put some work in.&lt;/p&gt;

&lt;p&gt;To prep, I put together two lists of questions (compiled from these excellent resources) -- ones for me to ask the interviewer ("Questions for them") and ones I'd expect to have to answer myself ("Questions for you") -- and kept both lists in front of me to reference as needed during interviews. I wrote out short answers to all the "Questions for you" in advance, prepping a couple different examples for each, so I could choose one in the moment best suited for the role/team. I also made of a copy of the "Questions for them" for each company and took notes on their answers during the interview. Keeping track of all the different responses made it easier to compare and contrast these opportunities later, but also provide direct, specific feedback afterwards, including thank you notes ✨&lt;/p&gt;

&lt;p&gt;I ended up putting more work into these questions than more purely technical prep (memorizing algorithms, etc). That might surprise you, but it unquestionably paid off. Having this Q&amp;amp;A at the ready enabled me to get the information I needed from each interviewer and have a fun conversation while doing so. And when it came time to make a decision, it was easy to compare notes and say yes to the right team.&lt;/p&gt;

&lt;p&gt;Below are both lists. You'll notice the questions aren't specific to any particular role, stack, or level. Rather, they're intended to be broadly applicable for anyone interviewing for a role on an engineering team -- or at least give you a good starting point that you can refine and adapt to your specific situation. I hope they're as helpful for you as they were for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  QUESTIONS FOR THEM
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🎯 Opportunities
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;What does this team need, and how can you help them?&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What's the story for this team in the coming year?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How much of the team's workload is maintenance vs. building new features?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are you working on now that you're most excited about?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's broken right now that you want to fix?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What separates someone who does &lt;em&gt;good&lt;/em&gt; work from someone who does &lt;em&gt;great&lt;/em&gt; work in this role?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are some of the skills you've learned on the job so far?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What kinds of tasks would I do on a "usual" day?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🚀 Process
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;How the team works is just as important as what the team works on.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Can you walk me through your team's development process, from planning to shipping?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;During your time on the team, what processes have you seen break down? How have you adjusted?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What does your onboarding process look like?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does your team have a standard development environment? Does everyone use it?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's your team's approach to pair programming?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What does your deployment process look like?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How quickly can you set up a new test environment for the product? (mins / hours / days)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  📣 Communication
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;How does this team like to communicate? Does it match your style?&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;How does your team deliver and handle feedback? Is there a formal process, ad hoc, both, neither?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How are differences of opinions resolved?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What kinds of tools and processes do you use to support remote/asynchronous work?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who takes notes during meetings?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who maintains documentation?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How much input/influence do developers have in team processes vs. the manager?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you raise issues when you observe them?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's a lot you can (and should) cover in this area, so check out the "Communication and Feedback" and "Dealing with Conflict" sections below for more questions that apply to both interviewer and interviewee.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤹‍♀️ Team Logistics
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Fact check your understanding of the team's structure.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;How much specialization is there in roles?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the junior/senior balance of the team?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tell me about your manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does the team include dedicated product managers, designers, or QA engineers?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who are your primary stakeholders? How often do you interact with them?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How much of the support burden falls on engineers vs. QA team vs. support team vs. the end user?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you have an on-call rotation? (If yes) Who's on it and how is it managed?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🏢 Company
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Don't miss the opportunity to get an inside perspective on the company itself.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What do you like about COMPANY compared to other companies you've worked at?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does the engineering culture differ from the overall company culture?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are some of the biggest challenges facing COMPANY right now?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are there known problems that COMPANY is trying to solve right now?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What problems would COMPANY be foolish not to fix in the next year?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  QUESTIONS FOR YOU
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🏢 Company
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Show them you've done your research.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Why COMPANY?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List company values. Prep an example for each one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do you think your potential impact at this company could be?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do you think the impact of this company could be?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What would make you choose our company over others?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you come in, what will your first order of business be?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🎯 Team/Role Fit
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;See if their expectations stack up to yours.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Why do you want to leave your current job?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are you looking for in your next role?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's important to you in a team?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are the three things that are most important to you in a job?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the role you tend to fill when in a team? ("Workhorse", "Leader", "Morale booster", "Coordinator", "Specialist", etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a time in the last week/month/year when you've been satisfied, energized, and productive at work. What were you doing?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  📣 Communication and Feedback
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Here's your chance to tell (and show) what you'd be like to work with as a teammate.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Talk about about how you collaborate with people who have a different background than you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about your code review process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about how you accept/deliver feedback to/from team members.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a time when you were communicating with someone and they did not understand you. What did you do?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Describe a situation where you needed to persuade someone to see things your way. What steps did you take? What were the results?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have you ever had to "sell" an idea to your coworkers or group? How did you do it? What were the results?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's one critical piece of feedback you've received that was really difficult to hear? Why was it difficult and what did you do with that information? What did you learn about yourself?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's some constructive criticism that you got at your current job, and how have you tried to address it?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When was the last time you asked for direct feedback from a superior? Why?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🙅‍♀️ Dealing with Conflict
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;These questions can be some of the most revealing -- for you and them. Stay alert for red flags.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Give an example of when you had to work with someone who was difficult to get along with. How did you handle interactions with that person?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Everybody has off days. How do you handle those?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do you do if a team member is having an off-day?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you have an example of how you have boosted morale in your previous role?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do you do when you don't see eye-to-eye with a team member? How do you move forward with a project?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a time when you had to admit you were wrong. What did you learn?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Describe a time when you felt stressed or overwhelmed. How did you handle it?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🆕 Dealing with Change
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Same as above, these questions can tell you as much about the company as the candidate. Be ready with clarifying follow-up questions.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Can you share an experience where a project dramatically shifted directions at the last minute? What did you do?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about the last time something significant didn't go according to plan at work. What was your role? What was the outcome?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about the biggest change that you have had to deal with. How did you adapt to that change?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a time when you had to adjust to a colleague's working style in order to complete a project or achieve your objectives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Describe a situation in which you embraced a new system, process, technology, or idea at work that was a major departure from the old way of doing things.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recall a time when you were assigned a task outside of your job description. How did you handle the situation? What was the outcome?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  📚 Learning and Growth
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;How much learning and growth is expected as part of this role, and does it line up with what you're looking for?&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What are some things you want to learn more about?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do you read to stay up-to-date?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What was the best new thing you learned in the last year?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do you do in your job that's not in your job description? How did you identify those opportunities?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Describe a time when you volunteered to expand your knowledge at work, as opposed to being directed to do so.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Describe a skill you had to acquire on-the-job to accomplish something you needed to do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a time when you were asked to do something you had never done before. How did you react? What did you learn?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ⏰ Planning and Time Management
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;How do you get stuff done?&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Imagine you are starting a new project (pick a sample project related to the role) - take me through your initial planning process?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a project that you planned. How did you organize and schedule the tasks?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a time when you had to juggle several projects at the same time. How did you organize your time? What was the result?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give an example of a time when you delegated an important task successfully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you determine what amount of time is reasonable for a task?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a time you set difficult goals. What did you do to achieve them? Walk me through the process and purpose.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When it's crunch time, how do you handle a big volume of work?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does your workflow change when you have a generous deadline vs. a tight deadline?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you balance getting your work done vs. being available to help teammates or chip in on team tasks like bug reports or out of process tasks that pop-up?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🦸‍♀️ Leadership
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;What kind of leader are you? What kind of leader do you want to work with?&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Give an example of a time when you felt you led by example. What did you do and how did others react?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Describe the best partner or supervisor with whom you've worked. What part of their managing style appealed to you?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recall a time when your manager was unavailable when a problem arose. How did you handle the situation? With whom did you consult?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the the toughest decision you had to make in the last six months?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🏆 Accomplishments
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Go ahead, brag a bit.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Discuss a project or two that you're very proud of.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the biggest career goal you've ever achieved?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about one of your favorite experiences working with a team and your contribution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a project you were primarily/solely responsible for shipping end-to-end (from ideation to launch). What inspired the idea? What determined what features you built and didn't build?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  👩‍💻 Expertise
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Demonstrate your smarts.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Give two scenarios where you would and wouldn't use LANGUAGE (ex. Ruby, Elixir, Go, etc).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give two scenarios where you would and wouldn't use FRAMEWORK (ex. React, Node, etc).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talk about about a recent project and what you(r team) could have done better.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are some of your coding pet peeves or issues that you make your mission to correct?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are some of your favorite tools to work with? What are the tools you're most comfortable with? Which aren't you comfortable with?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are some strategies you use to navigate ambiguity in the workplace? (e.g. feature requirements, management decisions, etc)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🏄‍♀️ Non-work life
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Don't forget about sharing a little bit about you, as a person.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What does work/life balance look like for you?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do you do for fun?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the most interesting thing about you that's not on your resume?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the biggest misconception your co-workers have about you and why do they think that?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/viraptor/reverse-interview"&gt;viraptor/reverse-interview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://yangshun.github.io/tech-interview-handbook/"&gt;Tech Interview Handbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.keyvalues.com/culture-queries"&gt;Key Values, "Culture Queries"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lever.co/blog/software-engineer-interview-questions-to-ask/"&gt;Lever, "Software Engineer Interview Questions to Ask"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.forbes.com/sites/laurencebradford/2016/11/17/15-questions-technical-hiring-managers-love-to-ask-interviewees"&gt;Laurence Bradford, "15 Questions Technical Hiring Managers Love To Ask In Interviews "&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillcrush.com/2017/05/01/technical-interviews/"&gt;Scott Morris, "The Most Important Technical Interview Questions You Need to Prepare For"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://firstround.com/review/the-best-interview-questions-weve-ever-published/"&gt;Todd Jackson, "The Best Interview Questions We've Ever Published"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sarahscode/interviewing-your-interviewer-how-to-know-what-questions-to-ask-at-an-interview-3mpm"&gt;Sarah Katz, "Interviewing Your Interviewer: How To Know What Questions To Ask At An Interview"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/stetsenko_me/20-questions-to-ask-a-recruiter-when-looking-for-a-new-tech-job-51g3"&gt;Andrew Stetsenko, "20 Questions To Ask A Recruiter When Looking For A New Tech Job"&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>interviewing</category>
      <category>interview</category>
    </item>
    <item>
      <title>TIL How to Select Merge with Ecto.Query</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Fri, 20 Sep 2019 02:01:54 +0000</pubDate>
      <link>https://forem.com/ktravers/til-how-to-select-merge-with-ecto-query-1944</link>
      <guid>https://forem.com/ktravers/til-how-to-select-merge-with-ecto-query-1944</guid>
      <description>&lt;p&gt;Here's the scenario: you're working with Elixir and Ecto, and you need to retrieve data from a table plus maybe a field or two from an unassociated table. In the past, whenever I ran into this, I'd spin up something I wasn't totally satisfied with - maybe updating the schema(s), breaking it up into multiple queries, or building a multi-select statement if I was feeling fancy.&lt;/p&gt;

&lt;p&gt;Happily, today I learned there's a better way. You can accomplish the same end result in a single query expression with &lt;code&gt;Ecto.Query#select_merge/3.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's run through an example to see it in action.&lt;/p&gt;

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

&lt;p&gt;Say you work at a school with an admissions department, and you've been tasked with displaying an event log showing all the events related to a given admission, organized into three columns: 1) date, 2) action taken, and 3) who the action was taken by.&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%2Fmiro.medium.com%2Fmax%2F2668%2F1%2A71xPk-6eU5-GAXn9ImMjqw.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%2Fmiro.medium.com%2Fmax%2F2668%2F1%2A71xPk-6eU5-GAXn9ImMjqw.png" alt="Event log table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start with, we have an &lt;code&gt;AdmissionEvent&lt;/code&gt; schema that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"admission_events"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:action&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="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admission_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admitter_uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:occurred_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:naive_datetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and a &lt;code&gt;User&lt;/code&gt; schema that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:full_name&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="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem here is the admitter's full name lives on the users table, which currently isn't associated with the admissions_events table. So if we did a straight-forward select query, we'd end up with the admission events we need to populate the table, but not the admitters' full names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;from:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"admission_events"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:action&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="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admission_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admitter_uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:occurred_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:naive_datetime&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="n"&gt;for_admission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="no"&gt;AdmissionEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ae&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;where:&lt;/span&gt; &lt;span class="n"&gt;ae&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;admission_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;admission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;order_by:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;desc:&lt;/span&gt; &lt;span class="n"&gt;ae&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;occurred_at&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Taking our query function for a spin in console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(1)&amp;gt; admission = Repo.get(Admission, 1)
iex(2)&amp;gt; AdmissionEvent.for_admission(admission) |&amp;gt; Repo.all()
[
  %Registrar.Tracking.AdmissionEvent{
    __meta__: #Ecto.Schema.Metadata&amp;lt;:loaded, "admission_events"&amp;gt;,
    action: "Student Admitted",
    admission_id: 3,
    admitter_uuid: "7edd4d7f-a790-41f9-b4ef-16f1dc3b33ea",
    id: 1,
    occurred_at: ~N[2019-07-29 02:22:18]
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fmiro.medium.com%2Fmax%2F2400%2F0%2AK1SakwybU7UPsrEn" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F2400%2F0%2AK1SakwybU7UPsrEn" alt="Event log missing name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, how do we want to go about getting the full name? We've got lots of options to choose from, but for this post, we'll compare two: one folks might reach for first (adding an association and preloading data) and one we'll hopefully reach for more often moving forward (select merge).&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: Add an Association and Preload the Data
&lt;/h2&gt;

&lt;p&gt;If we associate the &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;admissions_events&lt;/code&gt; tables, then we can preload the associated &lt;code&gt;User&lt;/code&gt; struct and read the full name from it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;from:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"admission_events"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:action&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="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admission_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admitter_uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:occurred_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:naive_datetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# New association&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;foreign_key:&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:full_name&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="c1"&gt;# New association&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admission_events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;AdmissionEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trying out our new association in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(1)&amp;gt; admission = Repo.get(Admission, 1)
iex(2)&amp;gt; events = AdmissionEvent.for_admission(admission) |&amp;gt; Repo.all() |&amp;gt; Repo.preload(:admitter)
[
  %Registrar.Tracking.AdmissionEvent{
    __meta__: #Ecto.Schema.Metadata&amp;lt;:loaded, "admission_events"&amp;gt;,
    action: "Student Admitted",
    admission_id: 3,
    admitter: %Registrar.User{
      __meta__: #Ecto.Schema.Metadata&amp;lt;:loaded, "users"&amp;gt;,
      id: 1,
      name: "Albus Dumbledore",
      uuid: "7edd4d7f-a790-41f9-b4ef-16f1dc3b33ea"
    },
    admitter_uuid: "7edd4d7f-a790-41f9-b4ef-16f1dc3b33ea",
    id: 1,
    occurred_at: ~N[2019-07-29 02:22:18]
  }
]
iex(3)&amp;gt; event = List.first(events)
iex(4)&amp;gt; event.admitter.name
"Albus Dumbledore"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach gets the job done, but it's a little heavy. We only need the admitter's full name, so why retrieve an entire User struct? You can also see how this pattern could lead to a super cluttered User schema. Right now it has many admission_events, but soon it could have many application_events, interview_events, billing_events, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: ✨ Select Merge ✨
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Ecto.Query#select_merge/3&lt;/code&gt; gives us an option that's much more succinct and precise. Check out this slickness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;from:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Registrar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;AdmissionEvent&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"admission_events"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:action&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="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admission_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admitter_uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:occurred_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:naive_datetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;###### STEP ONE #######&lt;/span&gt;
    &lt;span class="c1"&gt;#  Add Virtual Field  #&lt;/span&gt;
    &lt;span class="c1"&gt;#######################&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admitter_name&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;virtual:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;for_admission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="no"&gt;AdmissionEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ae&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;where:&lt;/span&gt; &lt;span class="n"&gt;ae&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;admission_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;admission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;order_by:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;desc:&lt;/span&gt; &lt;span class="n"&gt;ae&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;occurred_at&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

      &lt;span class="c1"&gt;#### STEP TWO ####&lt;/span&gt;
      &lt;span class="c1"&gt;#  Join on User  #&lt;/span&gt;
      &lt;span class="c1"&gt;##################&lt;/span&gt;
      &lt;span class="ss"&gt;join:&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;on:&lt;/span&gt; &lt;span class="n"&gt;ae&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;admitter_uuid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="c1"&gt;############ STEP THREE #############&lt;/span&gt;
      &lt;span class="c1"&gt;#  Select Merge into Virtual Field  #&lt;/span&gt;
      &lt;span class="c1"&gt;#####################################&lt;/span&gt;
      &lt;span class="ss"&gt;select_merge:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;admitter_name:&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trying out select merge in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(1)&amp;gt; admission = Repo.get(Admission, 1)
iex(2)&amp;gt; AdmissionEvent.for_admission(admission) |&amp;gt; Repo.all()
[
  %Registrar.Tracking.AdmissionEvent{
    __meta__: #Ecto.Schema.Metadata&amp;lt;:loaded, "admission_events"&amp;gt;,
    action: "Student Admitted",
    admission_id: 3,
    admitter_name: "Albus Dumbledore",
    id: 1,
    occurred_at: ~N[2019-07-29 02:22:18]
  }
]
iex(3)&amp;gt; event = List.first(events)
iex(4)&amp;gt; event.admitter_name
"Albus Dumbledore"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding a virtual field and populating it with &lt;code&gt;select_merge&lt;/code&gt;, we end up with a much lighter-weight solution. We get exactly the data we need without adding any new associations, keeping our schemas decoupled. Plus we have a pattern to follow that's a little more extensible moving forward, should we need to introduce event logs for different types of events.&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%2Fmiro.medium.com%2Fmax%2F3200%2F0%2AzImY0s5zkUkGdkgT" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3200%2F0%2AzImY0s5zkUkGdkgT" alt="Event log table with full name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Ecto.Query#select_merge/3&lt;/code&gt; allows us to populate a virtual field directly within a select query, giving us all kinds of flexibility when it comes to designing schemas and composing queries.&lt;/p&gt;

&lt;p&gt;10/10 Would compose again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/ecto/Ecto.Query.html#select_merge/3" rel="noopener noreferrer"&gt;Ecto.Query#select_merge/3 docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query.ex#L1168-L1209" rel="noopener noreferrer"&gt;Ecto.Query#select_merge/3 source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elixir</category>
      <category>ecto</category>
      <category>functional</category>
    </item>
    <item>
      <title>Pattern Matching in Elixir</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Fri, 27 Apr 2018 14:36:40 +0000</pubDate>
      <link>https://forem.com/flatironschool/pattern-matching-in-elixir-33m1</link>
      <guid>https://forem.com/flatironschool/pattern-matching-in-elixir-33m1</guid>
      <description>&lt;p&gt;At the &lt;a href="https://flatironschool.com" rel="noopener noreferrer"&gt;Flatiron School&lt;/a&gt;, our mission is to help people learn how to code. That means that as a member of the engineering team, my work reminds me almost every day of that important, universal truth: learning new stuff is hard.&lt;/p&gt;

&lt;p&gt;Take learning to play a musical instrument, for example, like guitar. When you start, you have these lofty aspirations. You wanna be the next David Bowie. But when you’re first starting out, that dream is so, so far away. It takes a ton of hard work to get there, and it’s easy to get discouraged. Without some early wins, you might give up.&lt;/p&gt;

&lt;p&gt;You need to learn that one cool riff that gets you hooked, where you don’t wanna put the guitar down, because now you’re in it.&lt;/p&gt;

&lt;p&gt;It’s kinda the same thing with &lt;a href="https://elixir-lang.org/" rel="noopener noreferrer"&gt;Elixir&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lots of folks are excited about the language because of all the great things you get from using it - concurrency, fault tolerance, scalability - the hype list goes on and on.  But none of these are things you can enjoy right away. You pretty much have to build and ship an entire app to production before you really start seeing any of this good stuff.&lt;/p&gt;

&lt;p&gt;You need a quick win to keep you going, you need that cool riff. And for me, that cool riff was pattern matching.&lt;/p&gt;

&lt;p&gt;So let's break down what it is and why it's so great.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Match Operator
&lt;/h3&gt;

&lt;p&gt;To understand pattern matching in Elixir, start by reframing the way you think about tying values to variables. Take the statement &lt;code&gt;x = 1&lt;/code&gt;. You probably read that as "x equals 1", where we're assigning the value &lt;code&gt;1&lt;/code&gt; to the variable &lt;code&gt;x&lt;/code&gt;, right?&lt;/p&gt;

&lt;p&gt;Welp, not in Elixir.&lt;/p&gt;

&lt;p&gt;In that statement, the &lt;code&gt;=&lt;/code&gt; is known as the "match operator", and it's not doing any assigning. Instead, it's evaluating whether the value on the right &lt;em&gt;matches&lt;/em&gt; the pattern on the left. If it's a match, then the value is bound to the variable [1]. If not, then a &lt;code&gt;MatchError&lt;/code&gt; is raised.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;/th&gt;
&lt;th&gt;=&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;pattern&lt;/td&gt;
&lt;td&gt;match operator&lt;/td&gt;
&lt;td&gt;value&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What does it mean to "match"? It means the value on the right matches the form and sequence of the pattern on the left.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple Examples
&lt;/h3&gt;

&lt;p&gt;Let's run through the basics of pattern matching with these simple examples below.&lt;/p&gt;

&lt;h4&gt;
  
  
  Binding on Match
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the match evaluates to true, since anything on the right-hand-side will match on an empty variable, so the empty variable on the left is bound to the value on the right.&lt;/p&gt;

&lt;h4&gt;
  
  
  Match Without Binding
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of these statements are valid expressions, and they also both match (!!!)&lt;/p&gt;

&lt;p&gt;In the top expression, the match evaluates to true and the value is bound to the variable. In the bottom expression, the match evaluates to true, but nothing is bound, since variables can only be bound on the left side of the &lt;code&gt;=&lt;/code&gt; match operator. For example, the statement &lt;code&gt;2 = y&lt;/code&gt; would throw a &lt;code&gt;CompileError&lt;/code&gt;, since &lt;code&gt;y&lt;/code&gt; is not defined.&lt;/p&gt;

&lt;h4&gt;
  
  
  Re-binding
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you pattern match on a bound variable, like &lt;code&gt;x&lt;/code&gt; above, it will be rebound if it matches.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pin Operator
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; ** (MatchError) no match of right hand side value: 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't want the variable to be rebound on match, use the &lt;code&gt;^&lt;/code&gt; &lt;a href="https://elixir-lang.org/getting-started/pattern-matching.html#the-pin-operator" rel="noopener noreferrer"&gt;pin operator&lt;/a&gt;. The pin operator prevents the variable from being rebound by forcing a strict match against its existing value.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lists
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 2&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can pattern match on more complex data structures, like &lt;a href="https://hexdocs.pm/elixir/List.html" rel="noopener noreferrer"&gt;lists&lt;/a&gt;. Again, any left side variables will bound on a match.&lt;/p&gt;

&lt;h4&gt;
  
  
  List &lt;code&gt;[head | tail]&lt;/code&gt; Format
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; [2,3,4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One cool thing you can do with lists is pattern match on the head and tail. Use the &lt;code&gt;|&lt;/code&gt; syntax to bind the leftmost variable to the first element in the list and the remaining elements to the rightmost variable (these variables don't have to be named &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt;; you can choose any names you want).&lt;/p&gt;

&lt;p&gt;This syntax comes in handy when you have a list of elements you want to operate on one-by-one, since it allows you to recursively iterate over the list very cleanly and succinctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; [1,2,3,4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use this syntax to prepend elements to lists, too, if you're feeling fancy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;rest&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="c1"&gt;#=&amp;gt; ** (MatchError) no match of right hand side value: []&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch out for empty lists, though. You'll raise a &lt;code&gt;MatchError&lt;/code&gt; if you use this syntax on an empty list, since there's nothing to bind either variable to.&lt;/p&gt;

&lt;h4&gt;
  
  
  Match Errors
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; ** (MatchError) no match of right hand side value: [4,5,6,7]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind, the match will fail if you compare different size lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&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="ss"&gt;:foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bar&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; ** (MatchError) no match of right hand side value: {:foo, :bar}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Matches also fail if you try to compare two different data structures, like a list and a tuple.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tuples
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 2&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pattern matching with &lt;a href="https://hexdocs.pm/elixir/Tuple.html" rel="noopener noreferrer"&gt;tuples&lt;/a&gt; operates much the same as with lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; "success"&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"womp womp"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; ** (MatchError) no match of right hand side value: {:error, "womp womp"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One common pattern you'll see in Elixir is functions returning tuples where the first element is an &lt;a href="https://elixir-lang.org/getting-started/basic-types.html#atoms" rel="noopener noreferrer"&gt;atom&lt;/a&gt; that signals status, like &lt;code&gt;:ok&lt;/code&gt; or &lt;code&gt;:error&lt;/code&gt;, and the second element is a &lt;a href="https://elixir-lang.org/getting-started/basic-types.html#strings" rel="noopener noreferrer"&gt;string&lt;/a&gt; message.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;_&lt;/code&gt; Underscore Variable
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; "success"&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"bummer"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; "bummer"&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For times when you want to pattern match but don't care about capturing any values, you can use the &lt;code&gt;_&lt;/code&gt; underscore variable. This special reserved variable matches everything; it's a perfect catch-all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; ** (CompileError) iex:2: unbound variable _&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just be aware that &lt;code&gt;_&lt;/code&gt; really truly is a throw-away variable, in that you can't read from it. If you try, Elixir will throw a &lt;code&gt;CompileError&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what's the big deal?
&lt;/h3&gt;

&lt;p&gt;Maybe you're not blown away by the examples above. Elixir has some nice syntactic sugar for pattern matching... but what's so groundbreaking about that?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7vwlqech3gionk9wr50z.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%2F7vwlqech3gionk9wr50z.jpg" title="Shania Twain That Don't Impress Me Much" alt="Shania Twain That Don't Impress Me Much"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a look at some practical real world applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;p&gt;We'll start with a problem that's probably familiar to most web developers: displaying public-facing user “display names” based on user-inputted data.&lt;/p&gt;

&lt;p&gt;This was something I worked on recently in the &lt;a href="https://learn.co" rel="noopener noreferrer"&gt;Learn.co&lt;/a&gt; codebase. On our site, we like to encourage an active, friendly sense of community, so we display users' names (built from information volunteered by the user) in lots of places across the site, including the &lt;a href="http://blog.flatironschool.com/troubleshooting-learn-co-closer-look-ask-question-feature/" rel="noopener noreferrer"&gt;Ask a Question chat feature&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk1njvieocryrhjuyb6gc.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%2Fk1njvieocryrhjuyb6gc.png" title="Learn.co Ask a Question" alt="Learn.co Ask a Question"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Problem is, we don't require users to give us their full name or even set a username, so when it comes to building a public-facing display name, there's no guarantee that any "friendly" identifying information - first name, last name, or username - is available. Additionally, all of this information is inputted manually by the user, and while we sanitize it to some degree before persisting, weird stuff can still get through.&lt;/p&gt;

&lt;p&gt;To address this problem, our product team developed the following requirements:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the user has provided their first and last name, display both together as their full name&lt;/li&gt;
&lt;li&gt;If we don't have first or last name, check if the user has provided their username, and if yes, display the username in place of full name&lt;/li&gt;
&lt;li&gt;If we don't have any of the above, display a reasonable generic default (here, we'll just use "New User")&lt;/li&gt;
&lt;/ol&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%2Fs0lazciw766dk5bwk3fa.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%2Fs0lazciw766dk5bwk3fa.png" title="Display Name Logic" alt="Display Name Logic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How could we represent these conditions in code?&lt;/p&gt;

&lt;h4&gt;
  
  
  Javascript Example
&lt;/h4&gt;

&lt;p&gt;Writing that function in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" rel="noopener noreferrer"&gt;Javascript&lt;/a&gt; might look something like this:*&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;* I realize these examples are somewhat contrived, but bear with me. They're for illustrative purposes, not code review.&lt;/p&gt;

&lt;p&gt;There's a lot of things that make this function pretty hard to grok in one glance. First off, there's Javascript's punctuation-heavy syntax, which can be a little rough on the eyes if you've been away from it for a little while. All the nested conditionals add complexity, too, as well as mental overload. Then additionally, we're also doing some nil checking (via &lt;code&gt;length&lt;/code&gt;) and throwing in some string sanitation for good measure. All-in-all, not super readable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ruby Example
&lt;/h4&gt;

&lt;p&gt;If we switch to &lt;a href="https://www.ruby-lang.org/en/" rel="noopener noreferrer"&gt;Ruby&lt;/a&gt;, a language praised for being "developer-friendly", the situation doesn't improve much.&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;def&lt;/span&gt; &lt;span class="nf"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;username&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="s1"&gt;'New User'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We still have our nested conditionals, and this long, "pointy" method decidedly does not pass the &lt;a href="https://atom.io/packages/squint-test" rel="noopener noreferrer"&gt;Sandi Metz "squint test"&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Elixir Example
&lt;/h4&gt;

&lt;p&gt;Let's see if we can fare any better with Elixir.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="no"&gt;New&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, each conditional has been separated out into its own function clause. Unlike in other languages like Ruby, when we "overload" a function like this (e.g. make multiple function declarations with the same function name), we're not overwriting the original function. Instead, these are known as multi-clause functions, and when you call a function that has several clauses, it'll will try each clause (starting at the top of the file and moving down) until it finds one that matches.&lt;/p&gt;

&lt;p&gt;You want to put your most specific clauses at the top, since those will match first. If you put something too general at the top, then it'll match everything and none of the clauses below it will ever get hit. Luckily, Elixir is pretty cool and usually throws a warning if you make this mistake.&lt;/p&gt;

&lt;p&gt;Multi-clause functions allow us to break our conditional logic into the smallest, atomic pieces, thereby keeping it isolated, encapsulated, and much more legible. It's easy to tell at a glance what each of these function clauses is doing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Handling the Un-Happy Path
&lt;/h4&gt;

&lt;p&gt;But you might have noticed our Elixir example here has a bit of an unfair advantage. Most of the added complexity in the Ruby and Javascript examples came from handling &lt;code&gt;nil&lt;/code&gt; cases, and we're not checking for those at all in the Elixir example - yet.&lt;/p&gt;

&lt;p&gt;You might be tempted to throw a &lt;code&gt;case&lt;/code&gt; statement into the first &lt;code&gt;display_name/1&lt;/code&gt; function clause (more on function &lt;code&gt;name/arity&lt;/code&gt; syntax &lt;a href="https://elixirschool.com/en/lessons/basics/functions/#function-naming-and-arity" rel="noopener noreferrer"&gt;here&lt;/a&gt;). You'll want to resist, though, because &lt;code&gt;case&lt;/code&gt; statements are not The Elixir Way™.&lt;/p&gt;

&lt;p&gt;Your next thought might be to try adding more higher-specificity clauses to the top of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Unwieldy nil checks&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{})&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&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="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{})&lt;/span&gt;

  &lt;span class="c1"&gt;# Happy paths&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;do_trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="no"&gt;New&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, as you can see, this can get unwieldy fast. Today, we're checking for nils in three fields, but what if requirements change? Given the possible permutations of all the possible fields on User we need to check against, you could end up with a super long, bloated module.&lt;/p&gt;

&lt;p&gt;What to do instead? Elixir has our back here, too: &lt;a href="https://hexdocs.pm/elixir/master/guards.html" rel="noopener noreferrer"&gt;guard clauses&lt;/a&gt; to the rescue.&lt;/p&gt;

&lt;h4&gt;
  
  
  Guard Clauses
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"New User"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Elixir function declarations support &lt;a href="https://hexdocs.pm/elixir/master/guards.html" rel="noopener noreferrer"&gt;guard clauses&lt;/a&gt;, which are a handy tool for augmenting pattern matching with more complex checks. Guard clauses are a nice way to match against more complex patterns without adding too much clutter to your functions. Only a &lt;a href="https://hexdocs.pm/elixir/master/guards.html#list-of-allowed-expressions" rel="noopener noreferrer"&gt;handful of expressions&lt;/a&gt; are supported, and they're meant to be short and sweet.&lt;/p&gt;

&lt;p&gt;In the code block above, we've added &lt;code&gt;not is_nil()&lt;/code&gt; guards to our first two clauses. Thanks to guard clauses, just adding a couple extra characters was all we needed to protect against nil values.&lt;/p&gt;

&lt;h4&gt;
  
  
  Custom Guard Clauses
&lt;/h4&gt;

&lt;p&gt;Let's throw one more curveball into the mix. There's another case we need to guard against with display names, and that's where a user has given us their full name, but it contains &lt;a href="https://en.wikipedia.org/wiki/Personally_identifiable_information" rel="noopener noreferrer"&gt;personal identifying information (PII)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This situation actually used to happen not infrequently on Learn.co. For some reason on our public, free &lt;a href="https://learn.co/sign_up" rel="noopener noreferrer"&gt;Bootcamp Prep course sign up page&lt;/a&gt;, users would often enter their email in the full name field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fm6ujk4njij5rfkpbhkis.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%2Fm6ujk4njij5rfkpbhkis.png" title="Learn.co Bootcamp Prep course sign up form" alt="Learn.co Bootcamp Prep course sign up form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clearly, we needed to change something about this UI (and add more validations on user input, but that's a separate blog post). However, since the bad data exists, we need to protect against it, and we can do so via some more complex pattern matching techniques.&lt;/p&gt;

&lt;p&gt;So far, our &lt;code&gt;display_name/1&lt;/code&gt; function clauses look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"New User"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might be asking yourself, is now when we finally give up on this pattern matching thing and just add some logic inside the body of the first function clause? Surprise (not surprised) - the answer is NO. We haven't exhausted Elixir's pattern matching toolbox yet.&lt;/p&gt;

&lt;p&gt;In addition to predefined guard clause expressions, Elixir also supports &lt;a href="https://hexdocs.pm/elixir/master/guards.html#defining-custom-guard-expressions" rel="noopener noreferrer"&gt;custom guard clauses&lt;/a&gt;. Now "custom" doesn't mean you can throw any function in there; custom guard clauses still have to built from the limited list of allowed expressions. But they're still super handy for keeping things DRY and simple.&lt;/p&gt;

&lt;p&gt;You can create custom guards with macros, but the docs recommend defining them with &lt;code&gt;defguard&lt;/code&gt; or &lt;code&gt;defguardp&lt;/code&gt; because those perform "additional compile-time checks" (which sounds good to me).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Not recommend: macros&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Guards&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;defmacro&lt;/span&gt; &lt;span class="n"&gt;is_private&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="kn"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt;
      &lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Recommended: defguard&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Guards&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;defguard&lt;/span&gt; &lt;span class="n"&gt;is_private&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can add one more function clause to the top of our module to satisfy our PII requirement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Guards&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;is_private:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_private&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Redacted&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="err"&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="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"New User"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Wrap Up
&lt;/h4&gt;

&lt;p&gt;Thanks to the power of pattern matching and multi-clause functions, we now have clear, clean, and effective code to handle displaying user names. And as new requirements come up, we don't have to touch any of these existing methods. We can simply add new clauses as needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Guards&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;is_private:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;# function heads only&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_private&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first:&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last:&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Takeaways
&lt;/h3&gt;

&lt;p&gt;As mentioned back at the beginning, working with pattern matching in Elixir requires you to think a bit differently - but different in a good way. The way the language is designed - the paradigms it embraces, the functionality it supports - encourages you to follow general programming best practices. Pattern matching is one of the best examples of this.&lt;/p&gt;

&lt;p&gt;Take pattern matching on multi-clause functions. By supporting this, Elixir nudges you towards writing small, declarative functions - short functions that do one thing only, e.g. functions that follow the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="noopener noreferrer"&gt;Single Responsibility Principle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Likewise, by declaring the pattern you want to match against, you're sending a clear signal about what inputs you expect to receive. Your code becomes more self-documenting by default.&lt;/p&gt;

&lt;p&gt;Plus, since pattern matching is ubiqutious in the language, once you master this concept, you're set up to master it all. It's the perfect jumping off point for exploring all the other amazing things in Elixir built around this core concept, like &lt;a href="https://elixir-lang.org/getting-started/mix-otp/genserver.html" rel="noopener noreferrer"&gt;GenServers&lt;/a&gt;, &lt;a href="https://elixirschool.com/en/lessons/specifics/plug/" rel="noopener noreferrer"&gt;plug&lt;/a&gt;... the list goes on and on.&lt;/p&gt;

&lt;p&gt;All-in-all, Elixir encourages you to write code that’s 1) declarative 2) self-documenting and 3) well scoped. It’s helping you become a stronger programmer, and it's setting you up to become a true rockstar Elixir developer.&lt;/p&gt;

&lt;p&gt;Now that's impressive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fximup82et6hxwdcwbnaj.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fximup82et6hxwdcwbnaj.gif" title="That Does Impress Me Much" alt="That Does Impress Me Much"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any questions? Leave them in the comments below. Thanks for reading!&lt;/p&gt;

&lt;p&gt;Want to work on a team that builds &lt;a href="http://blog.flatironschool.com/built-learn-ide-browser/" rel="noopener noreferrer"&gt;cool stuff&lt;/a&gt; in Elixir? &lt;a href="http://flatironschool.com/careers" rel="noopener noreferrer"&gt;Flatiron School is hiring!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And for examples of more cool stuff our team has built recently, check out our newly launched &lt;a href="https://flatironschool.com/programs/free-data-science-bootcamp-prep/?utm_campaign=Sponsored_Content&amp;amp;utm_source=Dev.to&amp;amp;utm_medium=DSBCP" rel="noopener noreferrer"&gt;Data Science Bootcamp Prep course&lt;/a&gt;, featuring an Elixir-backed &lt;a href="https://jupyter.org/" rel="noopener noreferrer"&gt;Jupyter notebook&lt;/a&gt; integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Readings:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Elixir docs: &lt;a href="https://elixir-lang.org/getting-started/pattern-matching.html" rel="noopener noreferrer"&gt;Pattern Matching&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Elixir School: &lt;a href="https://elixirschool.com/en/lessons/basics/functions/#pattern-matching" rel="noopener noreferrer"&gt;Pattern Matching&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Anna Neyzberg, &lt;a href="https://blog.carbonfive.com/2017/10/19/pattern-matching-in-elixir-five-things-to-remember/" rel="noopener noreferrer"&gt;"Pattern Matching in Elixir: Five Things to Remember"&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Videos:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Joao Goncalves, &lt;a href="https://www.youtube.com/watch?v=zwPqQngLn9w&amp;amp;index=6&amp;amp;list=PLCFmW8UCDqfCA9kpbFirPEDoQYc9nCy_W" rel="noopener noreferrer"&gt;"Getting Started with Elixir: Pattern Matching versus Assignment"&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Dave Thomas, &lt;a href="https://www.youtube.com/watch?v=5hDVftaPQwY" rel="noopener noreferrer"&gt;Think Different (ElixirConf2014 Keynote)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Lance Halvorsen, &lt;a href="https://www.youtube.com/watch?v=E-3G7g0Dm7c" rel="noopener noreferrer"&gt;"Confident Elixir" (ElixirConf 2015)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Tutorials:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Code School, &lt;a href="http://campus.codeschool.com/courses/try-elixir/level/3/section/1/pattern-matching" rel="noopener noreferrer"&gt;Try Elixir - Pattern Matching&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="footnotes"&gt;Footnotes&lt;/h3&gt;

&lt;p&gt;[1] Binding vs. Assignment&lt;/p&gt;

&lt;p&gt;The distinction between variable binding vs. variable assignment is small, but critical when it comes to pattern matching in Elixir. For any readers familiar with Erlang, all the binding and re-binding variables above may have seemed odd. In Erlang, variables are immutable, and since Elixir is built on top of the Erlang VM, variables are immutable in Elixir, too.&lt;/p&gt;

&lt;p&gt;If variables are immutable, then why are we allowed to tie and re-tie values to variables with pattern matching?&lt;/p&gt;

&lt;p&gt;We have to drop down to machine-level memory management to get the answer. Assignment assigns data to a place in memory, so re-assigning a variable changes the data in place. Binding creates a reference to a place in memory, so re-binding just changes the reference, not the data itself.&lt;/p&gt;

&lt;p&gt;Think of the variable as a suitcase. Binding the variable is like slapping a label on the suitcase. Assigning is like swapping out the contents [&lt;a href="https://stackoverflow.com/a/48103225/3880374" rel="noopener noreferrer"&gt;source&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;For more context, Elixir creator José Valim has a nice post on &lt;a href="http://blog.plataformatec.com.br/2016/01/comparing-elixir-and-erlang-variables/" rel="noopener noreferrer"&gt;Comparing Elixir and Erlang variables&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>patternmatching</category>
      <category>ruby</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How To Work With Developers - A Guide for Non-Developers</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Fri, 27 Apr 2018 04:02:33 +0000</pubDate>
      <link>https://forem.com/ktravers/how-to-work-with-developers---a-guide-for-non-developers-35hk</link>
      <guid>https://forem.com/ktravers/how-to-work-with-developers---a-guide-for-non-developers-35hk</guid>
      <description>&lt;p&gt;Software developers, have you ever felt misunderstood by your non-developer teammates? It happens to most of us, which is why I wrote this post to help clear up some of the most common misunderstandings, miscommunications, and missed opportunities. Feel free to pass it along to anyone who’d love to have an easier time working with developers.&lt;/p&gt;

&lt;p&gt;Below, I'll be sharing my (completely unbiased 😉) perspective on how to work with software developers. My goal is that after reading this article, every reader feels confident they can work effectively with their development team thanks to some proven tools and strategies we'll review together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developers: They're Just Like Us... or are they?
&lt;/h3&gt;

&lt;p&gt;So why is this talk necessary? Are developers really so different from your average co-worker?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yes.&lt;/strong&gt; Yes, we absolutely are.&lt;/p&gt;

&lt;p&gt;Take Flatiron School's engineering team, for example. Here's a picture of us from last summer, happily hacking away in the park outside our office.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fi0oup9sloptcl9k1mwl7.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%2Fi0oup9sloptcl9k1mwl7.JPEG" title="Flatiron School engineers outdoors" alt="Flatiron School engineers outdoors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why are we in a park? Well, this was moments after our building was evacuated during a fire at about 5:30pm in the afternoon. When the alarms went off, the rest of the office did what you'd expect: went home for the day.&lt;/p&gt;

&lt;p&gt;Not us. Without any pre-planning or conversation, every single one of our engineers picked up their laptops, filed outside, sat down on the nearest benches, and immediately went back to work.&lt;/p&gt;

&lt;p&gt;Like I said, we're a little different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Bridge the Divide?
&lt;/h3&gt;

&lt;p&gt;As a &lt;a href="https://flatironschool.com/programs/software-engineering-immersive/" rel="noopener noreferrer"&gt;bootcamp graduate&lt;/a&gt;, I didn't begin my career as a programmer. I’ve worked in a number of different fields - both in and outside tech - and in every workplace, there’s been a divide between developers and the rest of the company.&lt;/p&gt;

&lt;p&gt;Having been on both sides of that divide, I like to think I have a uniquely well-informed perspective, and as far as I can tell, the problems are almost exclusively due to miscommunication.&lt;/p&gt;

&lt;p&gt;That’s a good thing, because it means that with a little empathy from both sides, we can bridge the divide. And we want to, because the rewards are unquestionably worth it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fhyec4wp5e0zscui56yfx.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%2Fhyec4wp5e0zscui56yfx.png" title="Much Business" alt="Much Business"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Succeeding here is in everyone's best interest. It's good for your business to have a happy, productive office. But it's also good on an individual level. Being able to communicate with the “other side” is one of the most valuable skillsets you can bring to the table.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An engineer who’s a good communicator is perceived as better than an engineer with more technical skills but poorer communication skills.&lt;/li&gt;
&lt;li&gt;Likewise, a non-technical person who can “speak developer” is perceived as more valuable, because engineers are more likely to get stuff done for them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what are some of the obstacles we're up against? We'll look at two of the biggest: vocabulary and misconceptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vocabulary
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Developer, engineer, programmer
&lt;/h4&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%2F8b9sjof89yoy0zva8ohe.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%2F8b9sjof89yoy0zva8ohe.png" title="Labels" alt="Labels"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's the difference between these terms? As far as your average day-to-day work is concerned, nothing. These terms all describe people who code. There's no need to make it any more complicated than that.&lt;/p&gt;

&lt;p&gt;For anyone interested in the technical distinction, check out this &lt;a href="http://www.skorks.com/2010/03/the-difference-between-a-developer-a-programmer-and-a-computer-scientist/" rel="noopener noreferrer"&gt;blog post from Alan Skorkin&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Feature Development
&lt;/h4&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%2F8ab5od0850xg29qis8qc.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%2F8ab5od0850xg29qis8qc.png" title="Scrum Cycle" alt="Scrum Cycle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What does the engineering workflow look like at most companies? Most startups follow some version of the agile scrum process, where team members from the Product, Engineering, and QA teams work together with stakeholders to deliver a feature.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product manager oversees feature ideation, manages backlog.&lt;/li&gt;
&lt;li&gt;Product manager works with stakeholders and engineering to identify discrete set of stories/tickets for sprint&lt;/li&gt;
&lt;li&gt;Product manager (and/or engineering manager) assigns tickets to developers.&lt;/li&gt;
&lt;li&gt;Developers work through stories, with daily standups and feedback from product manager.&lt;/li&gt;
&lt;li&gt;Engineering and product work with QA to fully test before launch&lt;/li&gt;
&lt;li&gt;Review (ideally with a “retro” where everyone involved provides feedback)&lt;/li&gt;
&lt;li&gt;Launch / deliver to stakeholders&lt;/li&gt;
&lt;li&gt;Repeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the ideal flow. See the “real” picture: &lt;a href="http://www.projectcartoon.com/cartoon/2" rel="noopener noreferrer"&gt;http://www.projectcartoon.com/cartoon/2&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Stories / Tickets
&lt;/h4&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%2Fke8uaal6ub5crtr0hjmv.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%2Fke8uaal6ub5crtr0hjmv.png" title="GitHub Projects" alt="GitHub Projects"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During a sprint, engineering work is broken down into stories (which you may also hear referred to as "tickets"). Each story represents a discrete task or unit of work.&lt;/p&gt;

&lt;p&gt;Tasks are typically assigned to an individual developer.&lt;/p&gt;

&lt;p&gt;At Flatiron School, we like to manage our project queues using Github Projects (read more &lt;a href="https://help.github.com/articles/about-project-boards/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/blog/2272-introducing-projects-for-organizations" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  The Stack
&lt;/h4&gt;

&lt;p&gt;You may hear engineers referring to the "stack".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What kind of stack are you working with?"&lt;/p&gt;

&lt;p&gt;"What's your stack look like?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wikipedia defines a software stack as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A set of software subsystems or components needed to create a complete platform such that no additional software is needed to support applications” - &lt;a href="https://en.wikipedia.org/wiki/Solution_stack" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Solution_stack&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's a diagram of our stack that supports &lt;a href="https://learn.co" rel="noopener noreferrer"&gt;Learn.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx4mog5ov1j702jtqka4i.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%2Fx4mog5ov1j702jtqka4i.jpeg" title="Learn.co Stack" alt="Learn.co Stack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, I mainly showed this diagram to scare you.&lt;/p&gt;

&lt;p&gt;If you ask an engineer to describe your company’s stack to you, they’ll probably sketch out something like this. Entities and relationships, more of a high level abstraction than exhaustive detail. And that’s the right amount of information for most people. Think about a car engine, for example. Most of us don’t need to know the exact inner workings. We can get by knowing that gas goes in and force for turning the wheels comes out.&lt;/p&gt;

&lt;p&gt;So don’t sweat having a perfect grasp on this stuff. It's complicated for everyone, even the most experienced engineers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Backend vs. Frontend vs. Full Stack
&lt;/h4&gt;

&lt;p&gt;You'll also hear engineers talking about what part of the stack they work in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We're looking for a front-end specialist."&lt;/p&gt;

&lt;p&gt;"She's a backend engineer."&lt;/p&gt;

&lt;p&gt;"We expect all our engineers to be fullstack engineers."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fulvo6hqeni63thqcrk9n.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%2Fulvo6hqeni63thqcrk9n.png" title="Full Stack" alt="Full Stack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These terms loosely refer to what part of the codebase the engineer spends most of their time in.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend deals with data handling.&lt;/li&gt;
&lt;li&gt;Frontend handles UI/UX (User Interface, User Experience).&lt;/li&gt;
&lt;li&gt;Fullstack can do a little bit of everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind the divisions between these categories are fluid / fuzzy. Few engineers are purely one or the other. Most work across multiple parts of the stack, mostly be necessity.&lt;/p&gt;

&lt;p&gt;Read more on the differences &lt;a href="http://blog.udacity.com/2014/12/front-end-vs-back-end-vs-full-stack-web-developers.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  API
&lt;/h4&gt;

&lt;p&gt;API stands for &lt;strong&gt;A&lt;/strong&gt;pplication &lt;strong&gt;P&lt;/strong&gt;rogram &lt;strong&gt;I&lt;/strong&gt;nterface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjw72ysdizujv0avcxyim.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%2Fjw72ysdizujv0avcxyim.png" title="API" alt="API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;APIs define an interface that developers can use to request and receive data from a data source.&lt;/p&gt;

&lt;p&gt;Flatiron School's founder, &lt;a href="https://flatironschool.com/about-flatiron-school" rel="noopener noreferrer"&gt;Avi Flombaum&lt;/a&gt;, likes to use the restaurant analogy to explain APIs. Say I go to a restaurant and I really want a grilled cheese sandwich. I'm not just going to walk into the kitchen and start grabbing sandwich ingredients. Instead, there's a protocol. I ask the waiter for a menu, and make my selection from the menu's pre-defined choices. My request goes in, then the waiter brings me back a grilled cheese sandwich.&lt;/p&gt;

&lt;p&gt;Think of that menu as your API. It has predefined choices set by the restaurant that allow you to request and receive food.&lt;/p&gt;

&lt;p&gt;A public API works the same way. For example, if I want to put a Twitter feed on my website, I can use &lt;a href="https://dev.twitter.com/overview/api" rel="noopener noreferrer"&gt;Twitter's API&lt;/a&gt; to request tweet data, following the rules they've defined and documented.&lt;/p&gt;

&lt;p&gt;Read more on the &lt;a href="https://www.handsonconnect.org/blog/2016/8/17/what-is-an-api-and-why-should-i-care" rel="noopener noreferrer"&gt;HandsConnect blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The :shipit: Squirrel
&lt;/h4&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%2Fnbvqvhbgo4bd2yjg612f.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%2Fnbvqvhbgo4bd2yjg612f.jpeg" title="shipit Squirrel" alt="shipit Squirrel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This little cutie started as an inside joke at &lt;a href="https://github.com" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, but its adorableness quickly permeated the industry. When your code has been approved to ship, your teammates tag it with the :shipit: squirrel, the universal mascot of pushing code.&lt;/p&gt;

&lt;p&gt;So if you notice your engineering team sharing a bunch of squirrel pictures, don’t worry - they haven’t lost their minds. They’re just excited to push some new code to your users.&lt;/p&gt;

&lt;p&gt;Read the full lore &lt;a href="https://www.quora.com/GitHub-What-is-the-significance-of-the-Ship-It-squirrel" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/blog/1271-how-we-ship-github-for-windows" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misconceptions
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Misconception 1
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;True or false?&lt;/strong&gt; "Engineers... do not like speaking with people. Coding all day is good fun, talking with people is torture."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Engineers are just as social as your average co-worker. We’re just very protective of our precious (and limited) attention span.&lt;/p&gt;

&lt;h5&gt;
  
  
  1. Choose the appropriate communication channel for the situation.
&lt;/h5&gt;

&lt;p&gt;Different situations call for difference means of communication. Choose the appropriate channel based on the urgency of the situation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Timeframe&lt;/th&gt;
&lt;th&gt;Appropriate Channel&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Emergency&lt;/td&gt;
&lt;td&gt;Cannot wait. Equivalent to pulling someone out of a meeting&lt;/td&gt;
&lt;td&gt;Tap on the shoulder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Urgent&lt;/td&gt;
&lt;td&gt;Within the hour&lt;/td&gt;
&lt;td&gt;Synchronous channel (ex. DM)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;General&lt;/td&gt;
&lt;td&gt;Within the next few days / weeks&lt;/td&gt;
&lt;td&gt;Asynchronous channel (ex. email)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h5&gt;
  
  
  2. Respect chain of command
&lt;/h5&gt;

&lt;p&gt;Most of the time, you’ll want to talk to a manager first, rather than an individual engineer. Managers are the ones who have the most information about their team’s availability, abilities, and work load. Trust them to triage your request appropriately.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type of request&lt;/th&gt;
&lt;th&gt;Contact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Feature request&lt;/td&gt;
&lt;td&gt;Product manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical issue&lt;/td&gt;
&lt;td&gt;Engineering manager / QA manager&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Misconception 2
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;True or false?&lt;/strong&gt; When you ask for something from an engineer, don't get too detailed. They're the experts, so let them decide how to do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Engineers are detail-oriented problem solvers. Ambiguity slows us down; the more blanks we have to fill in, the more likely we’ll end up with a final product that doesn’t make anyone happy.&lt;/p&gt;

&lt;p&gt;Here's a &lt;a href="https://www.salesforce.com/video/296975/" rel="noopener noreferrer"&gt;true story from Salesforce's engineering team&lt;/a&gt; about the importance of being precise. A Salesforce product manager asked that “when an account was updated, shoot the owner an email.”  The developer said ok. Then the first email the account owner received read “TRUE”.&lt;/p&gt;

&lt;p&gt;Remember to clearly define your desired &lt;strong&gt;outcome&lt;/strong&gt;, but not the means of getting there. For example, often times a stakeholder will ask for data in a specific format - like CSV - which they then take and upload into Google Sheets and spend hours making pivot tables, etc. An easier route would have been to just tell the developer that they need to know X from this data. The developer might know an easier, faster means of analyzing the data (using tools like &lt;a href="https://periscopedata.com" rel="noopener noreferrer"&gt;Periscope&lt;/a&gt;, for example).&lt;/p&gt;

&lt;p&gt;Finally, don’t hide things from developers; if you think feature requirements will change soon or eventually, disclose that up front. That way the engineers can adjust their design accordingly, with the right balance of flexibility vs. speed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Misconception 3
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;True or false?&lt;/strong&gt; Engineers love details and hate meetings, so don’t bring them into a project until you’ve mapped everything out completely in advance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bring engineers in early. Their insights can save you from sinking time and effort into unrealistic goals, and by including them in the decision-making process, you’ll help them feel more invested in the project and its outcomes.&lt;/p&gt;

&lt;p&gt;Cliff Gilley describes this problem very well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“..there’s a tendency in many companies to ‘insulate’ the development teams from ‘the business’... This is a very sideways way of thinking, which usually results in expecting people to execute without context — without understanding the vision, the strategy, the tactics, or especially the customer. And therein lies the problem — people are motivated most when they share a vision of what the future might be, and can see themselves and their contributions in that picture.” &lt;a href="https://community.uservoice.com/blog/work-effectively-engineers/" rel="noopener noreferrer"&gt;[source]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Exercises
&lt;/h3&gt;

&lt;p&gt;Let's practice what we've learned so far. All examples are credit &lt;a href="https://github.com/spencer1248" rel="noopener noreferrer"&gt;Spencer Rogers&lt;/a&gt;, one of our top engineers at &lt;a href="https://flatironschool.com/careers/" rel="noopener noreferrer"&gt;Flatiron School&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conversation 1: Project Manager to Engineer
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Project Manager:&lt;/strong&gt;&lt;br&gt;
How’s the password reset feature going?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer:&lt;/strong&gt;&lt;br&gt;
I started looking into the Postmark API and installed their client library, but I started running into some issues in my development environment because of an outdated library we’re using for image handling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Rough translation:&lt;/strong&gt; &lt;em&gt;I am working.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How could this make the project manager feel?&lt;/strong&gt; &lt;em&gt;Confused, agitated, stone-walled, impatient, questioning the common sense of the developer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this good communication?&lt;/strong&gt; &lt;em&gt;No.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What was the meaningful information?&lt;/strong&gt; &lt;em&gt;I need an update on your progress, so I can assess whether to assign more or less resources.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What would be useful to have said instead?&lt;/strong&gt; &lt;em&gt;I hit a roadblock, which set me back by ~1 day.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How could the other party respond to invite a better answer?&lt;/strong&gt; &lt;em&gt;How does this affect the original estimate? Do you need anything from me to get past this?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How could the initial question have been asked better?&lt;/strong&gt; &lt;em&gt;I’m working on assignments for next week. Can you give me a quick status update on the password reset feature?&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Conversation 2: Marketing Manager to Engineer
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Marketing manager to developer:&lt;/strong&gt;&lt;br&gt;
Can you please build us something to address the sign-up conversion rate by the end of the day?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Rough translation:&lt;/strong&gt; &lt;em&gt;Can you do something you don’t know how to do in an arbitrary time frame that may or may not be realistic?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this good communication?&lt;/strong&gt; &lt;em&gt;No.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does this make the developer feel?&lt;/strong&gt; &lt;em&gt;Overwhelmed, unsupported, disrespected, cog-in-machine, irritated that question is so ignorant of their capabilities, reality, etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What was the meaningful information?&lt;/strong&gt; &lt;em&gt;We need something built to solve a business problem.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What would be useful to have said instead?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;a) Not a lot of people are signing up for the new service. Do you know how we can fix it? No? Well let’s figure something out that you can build within our deadline.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;b) Not a lot of people are signing up for the new service. Do you know how we can fix it? Yes? That’s great. How long would something like that take to build? (then potentially) That’s too long, is there a simpler or interim solution we could use?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How could the other party respond to invite a better answer?&lt;/strong&gt; &lt;em&gt;I can try my best, but I’ve never had to do that before and I don’t have any idea how long it will take or whether it will be effective.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Conversation 3: Engineer to CEO
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Developer:&lt;/strong&gt;&lt;br&gt;
I just used a really cool algorithm to guess similar words using something called &lt;a href="http://blog.kate-travers.com/levenshtein-for-president/" rel="noopener noreferrer"&gt;“Levenshtein distance”&lt;/a&gt;. The data consistency problem should be fixed by EOD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CEO:&lt;/strong&gt;&lt;br&gt;
Ok, but what about the landing page update?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Developer Rough translation:&lt;/strong&gt; &lt;em&gt;I just did something cool to fix the problem and deliver it on time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CEO Rough translation:&lt;/strong&gt; &lt;em&gt;I expect you to fix problems like this, what about the stuff that’s actually going to move this business forward?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this good communication?&lt;/strong&gt; &lt;em&gt;Nope.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does the developer feel?&lt;/strong&gt; &lt;em&gt;Proud, unhappy that their work wasn't appreciated, rushed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does the CEO feel?&lt;/strong&gt; &lt;em&gt;Agitated that something that set the business back is being celebrated before something that is completing the CEO’s vision of the company is finished.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two perspectives:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;1) Developers spend 99% of their day working on stuff that many people can’t see or appreciate. It can be frustrating, especially when they’ve built something they’re proud of and it’s all they’ve thought about for weeks.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Some developers make themselves less efficient simply in order to manage the expectations of the people waiting on their product. It is tough to gauge if you don’t have a window that you can trust.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There’s also many ways to be a “good” developer. At a small startup, a good metric is whether the developer is producing value for the company, which can be difficult to measure. Many of the ways a developer produces value are not visible to a lot of the company.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;CEOs ultimately want their company to be successful. As a developer (or anyone), you should do your best to understand the high level goals of the company.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This doesn’t mean that they’re going to be mean by default. If you had two companies, both producing the exact same revenue, but one had a healthy culture and one had an unhealthy culture, which one would you choose as a CEO?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2) It might be better to find someone else to tell about your cool algorithm, though.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Conversation 4: Engineer to Product Manager
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Developer to product manager:&lt;/strong&gt;&lt;br&gt;
I’m working on the search feature and noticed that some of these filtering options don’t make sense together. What if we did it like this instead?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Rough translation:&lt;/strong&gt; &lt;em&gt;I was working on this but my common sense kicked in and realized it didn’t make sense. I have an idea that would fix it though.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this good communication?&lt;/strong&gt; &lt;em&gt;Yes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What was the meaningful information?&lt;/strong&gt; &lt;em&gt;Everything.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What would be useful to have said instead?&lt;/strong&gt; &lt;em&gt;Maybe an estimate for the proposal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How could this have gone wrong?&lt;/strong&gt; &lt;em&gt;If the dev had changed stuff without talking to someone. It doesn’t mean they have to give up total ownership of the product, but everyone should be on the same page. A lot of people have probably been thinking about this feature.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The best course of action here isn’t the best course of action everywhere. Have an understanding of how these things should work.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaways: Things You Can Do Right Away For Great Good
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Take an engineer out for coffee :)

&lt;ul&gt;
&lt;li&gt;Get their perspective on this subject - what’s their advice for working well with developers?&lt;/li&gt;
&lt;li&gt;Ask them about what they’re working on&lt;/li&gt;
&lt;li&gt;Ask about non-work stuff too&lt;/li&gt;
&lt;li&gt;In general: spend time with people from other departments - game nights, lunches, coffee&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Attend open engineering events (demos, retros, code talks)

&lt;ul&gt;
&lt;li&gt;Get familiar with the team and what they’re working on&lt;/li&gt;
&lt;li&gt;Get comfortable with shared vocabulary, company terminology&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Get into the product

&lt;ul&gt;
&lt;li&gt;Look for opportunities to work with developers (doesn’t have to be on a development project; could be event organizing, etc)&lt;/li&gt;
&lt;li&gt;Volunteer to help out on other teams. Some personal examples:&lt;/li&gt;
&lt;li&gt;helping with QA / user testing&lt;/li&gt;
&lt;li&gt;hosting meetup events (and helping with set up / tear down)&lt;/li&gt;
&lt;li&gt;writing blog posts&lt;/li&gt;
&lt;li&gt;user outreach&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Last but not least, let developers know when you appreciate their work. Thank you!&lt;/p&gt;

&lt;p&gt;Interested in working on a team that values effective cross-departmental communication? &lt;a href="https://flatironschool.com/careers/" rel="noopener noreferrer"&gt;Flatiron School is hiring!&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources: Articles
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.smashingmagazine.com/2014/06/communicating-effectively-in-projects/" rel="noopener noreferrer"&gt;Krzysztof Rakowski - How To Communicate Effectively In IT Projects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/the-year-of-the-looking-glass/how-to-work-with-engineers-a3163ff1eced" rel="noopener noreferrer"&gt;Julie Zhuo - How to Work with Engineers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.nczonline.net/blog/2012/06/12/the-care-and-feeding-of-software-engineers-or-why-engineers-are-grumpy/" rel="noopener noreferrer"&gt;Nicholas Zakas - The care and feeding of software engineers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://community.uservoice.com/blog/work-effectively-engineers/" rel="noopener noreferrer"&gt;Cliff Gilley - How to Work Effectively With Engineers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.peachpit.com/articles/article.aspx?p=99803" rel="noopener noreferrer"&gt;June Cohen - How to Work with Engineers on a Web Development Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.forbes.com/sites/stellafayman/2013/03/14/5-best-practices-for-working-with-developers/#5274f3153ef1" rel="noopener noreferrer"&gt;Stella Garber - 5 Best Practices for Working with Developers&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Resources: Videos
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="http://www.mindtheproduct.com/2016/07/building-happy-product-teams-like-heist-teams-laura-klein/" rel="noopener noreferrer"&gt;Laura Klein - Building Happy Product Teams like Heist Teams&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=mweTM1hsn84" rel="noopener noreferrer"&gt;Ryan Hughes - Bridging the Gap between Designers and Developers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.salesforce.com/video/296975/" rel="noopener noreferrer"&gt;Salesforce Case Study - How Admins And Developers Can Collaborate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.mindtheproduct.com/2016/04/product-owners-how-to-get-your-development-team-to-love-you/" rel="noopener noreferrer"&gt;​Ron Lichty - How to Get Your Development Team to Love You&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>crossfunctional</category>
      <category>collaboration</category>
      <category>communication</category>
    </item>
    <item>
      <title>How to Run Ecto Migrations on Production</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Fri, 27 Apr 2018 03:15:42 +0000</pubDate>
      <link>https://forem.com/ktravers/how-to-run-ecto-migrations-on-production-5ai8</link>
      <guid>https://forem.com/ktravers/how-to-run-ecto-migrations-on-production-5ai8</guid>
      <description>&lt;p&gt;You'd think the answer to this question would be a simple Google search away. Unfortunately, that wasn't the case for me this afternoon, working on a &lt;a href="http://phoenixframework.org/"&gt;Phoenix&lt;/a&gt; project with a newly-added &lt;a href="https://hexdocs.pm/ecto/getting-started.html"&gt;Ecto&lt;/a&gt; backend. In an effort to save others (and let's be honest, future me) the same frustration, here's the most straight-forward solutions I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Doesn't Work
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://elixirschool.com/lessons/basics/mix/"&gt;&lt;code&gt;Mix&lt;/code&gt;&lt;/a&gt;. &lt;code&gt;Mix&lt;/code&gt; tasks aren't compiled into your deployed release, and as evidenced in &lt;a href="https://github.com/bitwalker/exrm/issues/67"&gt;this exciting discussion&lt;/a&gt;, there's no plans to change this any time soon.&lt;/p&gt;

&lt;p&gt;So don't try using your trusty local &lt;code&gt;mix ecto.migrate&lt;/code&gt; task on production. Not gonna help you here.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://hexdocs.pm/ecto/Ecto.Migrator.html"&gt;Ecto.Migrator&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Ecto ships with &lt;a href="https://hexdocs.pm/ecto/Ecto.Migrator.html"&gt;Ecto.Migrator&lt;/a&gt;, a first-class module for Ecto's migration API.&lt;/p&gt;

&lt;p&gt;Run it manually by ssh'ing onto your app server, attaching to your Phoenix app, and running the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;path = Application.app_dir(:my_app, "priv/repo/migrations")

Ecto.Migrator.run(MyApp.Repo, path, :up, all: true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ideally, you'd wrap up the above in its own task that can be called during your build and deployment process. Check out Plataformatec's blog for a &lt;a href="http://blog.plataformatec.com.br/2016/04/running-migration-in-an-exrm-release/"&gt;nice example&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. eDeliver
&lt;/h3&gt;

&lt;p&gt;Our app uses &lt;a href="https://github.com/edeliver/edeliver"&gt;&lt;code&gt;edeliver&lt;/code&gt;&lt;/a&gt; for deployments, and it has a super handy command for manually running migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix edeliver migrate production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we peek at the source, turns out this command actually just &lt;a href="https://github.com/edeliver/edeliver/blob/963610a90f67fc3671127e64df37a67ec365ef5b/lib/edeliver.ex#L124"&gt;wraps up &lt;code&gt;Ecto.Migrator&lt;/code&gt; for you&lt;/a&gt;, saving some precious keystrokes.&lt;/p&gt;

&lt;p&gt;To run successfully, you'll need to add &lt;code&gt;ECTO_REPOSITORY="MyApp.Repo"&lt;/code&gt; to your &lt;code&gt;.deliver/config&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Again, Plataformatec has a nice blog post on &lt;a href="http://blog.plataformatec.com.br/2016/06/deploying-elixir-applications-with-edeliver/"&gt;deploying your Elixir app with eDeliver&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Hi future me! Hope this post was still helpful the nth time around.&lt;/p&gt;

&lt;h3&gt;
  
  
  References:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/phoenixframework/phoenix_ecto"&gt;Phoenix Ecto Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/ecto/Ecto.Migrator.html"&gt;Ecto.Migrator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/edeliver/edeliver"&gt;eDeliver&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elixir</category>
      <category>ecto</category>
    </item>
    <item>
      <title>How My Bash Color Settings Broke edeliver</title>
      <dc:creator>Kate Travers</dc:creator>
      <pubDate>Fri, 27 Apr 2018 03:13:19 +0000</pubDate>
      <link>https://forem.com/ktravers/how-my-bash-color-settings-broke-edeliver-4p13</link>
      <guid>https://forem.com/ktravers/how-my-bash-color-settings-broke-edeliver-4p13</guid>
      <description>&lt;p&gt;Yep, you read that right. My bash color settings broke &lt;a href="https://github.com/edeliver/edeliver"&gt;edeliver&lt;/a&gt;, the tool my team uses to deploy our &lt;a href="https://elixir-lang.org/"&gt;Elixir&lt;/a&gt; apps.&lt;/p&gt;

&lt;p&gt;Now, anyone who's &lt;a href="http://blog.kate-travers.com/refash-your-bash/"&gt;tinkered with their &lt;code&gt;.bash_profile&lt;/code&gt;&lt;/a&gt; knows there's an infinite number of ways to totally bork your system. But this bug was well camouflaged, hiding inside a common, seemingly-benign bash setting I'd had in place for over two and a half years without issue - a bash setting you, too, might have on your machine RIGHT NOW 😱&lt;/p&gt;

&lt;p&gt;But don't worry, I tracked down the little bugger, so read on to save yourself the same hassle I went through. And for those of you in a rush, here's the tl;dr.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Problem&lt;/li&gt;
&lt;li&gt;Debugging Steps&lt;/li&gt;
&lt;li&gt;The Turning Point&lt;/li&gt;
&lt;li&gt;The Explanation&lt;/li&gt;
&lt;li&gt;The Solution&lt;/li&gt;
&lt;li&gt;Learnings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="the-problem"&gt;The Problem&lt;/h2&gt;

&lt;p&gt;I'd just started working on one of our Elixir projects, doing my best to learn a new codebase and a new language all at once. Things were going well until it came time to deploy changes. I could &lt;a href="https://github.com/edeliver/edeliver#build-commands"&gt;build a release&lt;/a&gt;, no problem, but I couldn't &lt;a href="https://github.com/edeliver/edeliver#deploy-commands"&gt;deploy&lt;/a&gt;; the command would fail every time with the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix edeliver deploy release to production &lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;X.X.X-XXX-XXXXXXX &lt;span class="nt"&gt;--verbose&lt;/span&gt;

DEPLOYING RELEASE OF MY_APP APP TO PRODUCTION HOSTS

&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Authorizing hosts
&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Authorizing release store host
&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Authorizing deploy hosts on release store
&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Uploading archive of release X.X.X-XXX-XXXXXXX from remote release store
Uploading release file failed
  &lt;span class="nb"&gt;source&lt;/span&gt;: /home/deployer/my_app/builds/complete/my_app_X.X.X-XXX-XXXXXXX.release.tar.gz on deployer@host
  destination: /home/deployer/my_app/my_app_X.X.X-XXX-XXXXXXX.tar.gz on deploy hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My teammates &lt;em&gt;could&lt;/em&gt; deploy using the same command; I was the only one getting this error. I tried running the command from my work and personal computers, and it errored out the same way consistently on both machines (I use shared &lt;a href="https://github.com/ktravers/dotfiles"&gt;dotfiles&lt;/a&gt;, so this wasn't super surprising).&lt;/p&gt;

&lt;h2 id="debugging-steps"&gt;Debugging Steps&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hard Reset&lt;/li&gt;
&lt;li&gt;Get Verbose&lt;/li&gt;
&lt;li&gt;Manual Workaround&lt;/li&gt;
&lt;li&gt;SSH Sanity Check&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="hard-reset"&gt;1. Hard Reset&lt;/h3&gt;

&lt;p&gt;My first recourse here was the same I use any time I hit a weird error: start over fresh. I deleted the project directory from my machine, re-cloned it back down, and tried deploying the master branch (which was already running on production). No dice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ Confirmed issue wasn't with something I'd changed in the codebase&lt;br&gt;&lt;br&gt;
❌ Didn't work. Deploy still failed.&lt;/p&gt;

&lt;h3 id="get-verbose"&gt;2. Get Verbose&lt;/h3&gt;

&lt;p&gt;I was running the deploy command with the &lt;code&gt;--verbose&lt;/code&gt; flag, but the edeliver error message wasn't telling me much about &lt;em&gt;why&lt;/em&gt; the command was failing (more on that later). I needed more info.&lt;/p&gt;

&lt;p&gt;On my teammate &lt;a href="http://hostiledeveloper.com/"&gt;Steven's&lt;/a&gt; excellent advice, I opened up &lt;code&gt;my_app/deps/edeliver&lt;/code&gt;, found the command that was failing by searching for the error message ("Uploading release file failed"), and flipped it into verbose debug mode by adding the &lt;code&gt;-vvvvv&lt;/code&gt; option (more &lt;code&gt;v&lt;/code&gt;'s == more verbose):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# https://github.com/edeliver/edeliver/blob/master/libexec/erlang#L685-L759&lt;/span&gt;

&lt;span class="c"&gt;# copies the release archive to the production hosts to the given path.&lt;/span&gt;
upload_release_archive&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;# lotsa code, omitted here for brevity&lt;/span&gt;
  ssh &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;-vvvvv&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ConnectTimeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSH_TIMEOUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$_release_store_host&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$_remote_job&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SILENCE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    error &lt;span class="s2"&gt;"Uploading release file failed&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  source: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;_release_store_path&lt;/span&gt;&lt;span class="p"&gt;%%/&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;_release_file&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; on &lt;/span&gt;&lt;span class="nv"&gt;$_release_store_host&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  destination: &lt;/span&gt;&lt;span class="nv"&gt;$_dest_file_name&lt;/span&gt;&lt;span class="s2"&gt; on deploy hosts"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gave me way more insight into what this script was trying (and failing) to do. Honestly, probably too much insight. Re-running the deploy command in verbose debug mode gave me back ~200 lines of output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix edeliver deploy release to production &lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;X.X.X-XXX-XXXXXXX &lt;span class="nt"&gt;--verbose&lt;/span&gt;

DEPLOYING RELEASE OF MY_APP APP TO PRODUCTION HOSTS

&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Authorizing hosts
&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Authorizing release store host
&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Authorizing deploy hosts on release store
&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Uploading archive of release X.X.X-XXX-XXXXXXX from remote release store
OpenSSH_7.4p1, LibreSSL 2.5.0
debug1: Reading configuration data /Users/kate/.ssh/config
debug1: /Users/kate/.ssh/config line 1: Applying options &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;
debug1: Reading configuration data /etc/ssh/ssh_config
debug2: resolving &lt;span class="s2"&gt;"xxx.xxx.xx.xxx"&lt;/span&gt; port XXX
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to xxx.xxx.xx.xxx &lt;span class="o"&gt;[&lt;/span&gt;xxx.xxx.xx.xxx] port XXX.
debug2: fd 3 setting O_NONBLOCK
debug1: fd 3 clearing O_NONBLOCK
debug1: Connection established.
debug3: &lt;span class="nb"&gt;timeout&lt;/span&gt;: 99999969 ms remain after connect
debug1: identity file /Users/kate/.ssh/id_rsa &lt;span class="nb"&gt;type &lt;/span&gt;1

&lt;span class="c"&gt;### approx 180 more lines...&lt;/span&gt;

debug3: send packet: &lt;span class="nb"&gt;type &lt;/span&gt;1
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
debug3: fd 2 is not O_NONBLOCK
Transferred: sent 4624, received 2996 bytes, &lt;span class="k"&gt;in &lt;/span&gt;0.2 seconds
Bytes per second: sent 20610.0, received 13353.7
debug1: Exit status 1
Uploading release file failed
  &lt;span class="nb"&gt;source&lt;/span&gt;: /home/deployer/my_app/builds/complete/my_app_X.X.X-XXX-XXXXXXX.release.tar.gz on deployer@host
  destination: /home/deployer/my_app/my_app_X.X.X-XXX-XXXXXXX.tar.gz on deploy hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Steven did the same thing on his machine, so we'd have his successful debug log for comparison.&lt;/p&gt;

&lt;p&gt;His output also gave us another valuable piece of information: the actual bash command &lt;a href="https://github.com/edeliver/edeliver/blob/master/libexec/erlang#L754-L755"&gt;&lt;code&gt;$_remote_job&lt;/code&gt;&lt;/a&gt; built by the &lt;a href="https://github.com/edeliver/edeliver/blob/master/libexec/erlang#L689"&gt;&lt;code&gt;upload_release_archive&lt;/code&gt; function&lt;/a&gt;, i.e. the one that copies the release from our build server to our production server, i.e. the one throwing the error. We'd follow that lead next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ Better output with verbose debug mode&lt;br&gt;&lt;br&gt;
✅ Confirmed exact point of failure&lt;br&gt;&lt;br&gt;
✅ Learned a new debugging technique (thanks Steven!)&lt;br&gt;&lt;br&gt;
❌ Hard to separate signal from noise&lt;/p&gt;

&lt;h3 id="manual-workaround"&gt;3. Manual Workaround&lt;/h3&gt;

&lt;p&gt;We'd pinpointed the command that was failing locally, so why not try running it directly from the build server?&lt;/p&gt;

&lt;p&gt;I ssh'd into our build server, switched to our deployer user, and ran the &lt;a href="https://github.com/edeliver/edeliver/blob/master/libexec/erlang#L754-L755"&gt;&lt;code&gt;$_remote_job&lt;/code&gt; command&lt;/a&gt; above. What do you know, it worked! The release archive was copied from the build server to our production server, as expected.&lt;/p&gt;

&lt;p&gt;I dropped back onto my local machine, commented out the &lt;a href="https://github.com/edeliver/edeliver/blob/master/libexec/erlang#L689"&gt;&lt;code&gt;upload_release_archive&lt;/code&gt; function&lt;/a&gt; from the edeliver script (since the archive was already copied over), and ran the deploy command. Success!&lt;/p&gt;

&lt;p&gt;So now things are getting interesting. When I run the command from my local as my &lt;code&gt;kate&lt;/code&gt; user, it fails. When I run it from our build server as &lt;code&gt;deployer&lt;/code&gt;, it succeeds. Conclusion: something's messed up with my user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ We found a usuable (albeit super manual) workaround&lt;br&gt;&lt;br&gt;
✅ Confirmed problem wasn't with our project's edeliver config&lt;br&gt;&lt;br&gt;
❌ Still can't deploy from my local&lt;/p&gt;

&lt;h3 id="sanity-check"&gt;4. Sanity Check&lt;/h3&gt;

&lt;p&gt;We'd narrowed down the issue to my user, so next step was to check my ssh config. I confirmed that my keys were on the required servers by ssh'ing in as my user... no problems there. Then I compared my &lt;code&gt;.ssh/config&lt;/code&gt; file to my teammates' config... nothing out of wack there either.&lt;/p&gt;

&lt;p&gt;I also tried deploying after removing everything from the following config files (testing each in isolation, one-by-one), still with zero success:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.ssh/known_hosts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.bashrc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.profile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Outcome:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ Confirmed problem wasn't with my ssh config&lt;br&gt;&lt;br&gt;
❌ Running out of ideas&lt;/p&gt;

&lt;h2 id="the-turning-point"&gt;The Turning Point&lt;/h2&gt;

&lt;p&gt;At this point, desperation was setting in. My teammates and I were stumped, and we'd run out of things to try.&lt;/p&gt;

&lt;p&gt;Enter Andres from &lt;a href="https://ozoneops.com/"&gt;OzoneOps&lt;/a&gt;, our devops contractor. I'd sent him Steven's and my output logs, and he was the first to notice a pretty important difference: in my output, the archive filename had a bunch of weird characters in it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Filename from Steven's output&lt;/span&gt;
my_app_X.X.X-XXX-XXXXXXX.release.tar.gz

&lt;span class="c"&gt;# Filename from Kate's output&lt;/span&gt;
my_app_&lt;span class="se"&gt;\0&lt;/span&gt;33[4&lt;span class="p"&gt;;&lt;/span&gt;38m&lt;span class="se"&gt;\0&lt;/span&gt;33[KX.X.X-XXX-XXXXXXX&lt;span class="se"&gt;\0&lt;/span&gt;33[m&lt;span class="se"&gt;\0&lt;/span&gt;33[K.release.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What was going on here? Where were those extra characters coming from?&lt;/p&gt;

&lt;p&gt;A quick Google search revealed that these are terminal escape sequences, or &lt;a href="https://en.wikipedia.org/wiki/ANSI_escape_code"&gt;ANSI escape codes&lt;/a&gt;. The terminal normally interprets these sequences as functions, not characters, so you can use them to format output, like adding color to the output of &lt;code&gt;grep&lt;/code&gt; or &lt;code&gt;ls&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;I like me some colors in my terminal output, so way back in the day (like, two and a half years ago), I added settings to my &lt;code&gt;.bash_profile&lt;/code&gt; to colorize my &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt; output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LSCOLORS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gxxxxxxxcxxxxxcxcxgxgx
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GREP_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--color=always'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GREP_COLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'4;38'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd never given these settings a second thought... until now. Turns out they've been a ticking time bomb, just waiting for this specific scenario.&lt;/p&gt;

&lt;h2 id="the-explanation"&gt;The Explanation&lt;/h2&gt;

&lt;p&gt;The settings above work their colorizing magic by adding ANSI escape codes to output from &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt; commands. For example, let's run &lt;code&gt;grep&lt;/code&gt; on &lt;code&gt;example.txt&lt;/code&gt; below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;example.txt
abcdef
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;abc example.txt
abcdef

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;--color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;always abc example.txt
abcdef
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems harmless, right? The escape codes are properly "escaped", interpretted as functions instead of characters... EXCEPT when your terminal doesn't know how to interpret the sequence. For example, look what happens when you pipe colorized &lt;code&gt;grep&lt;/code&gt; output into &lt;code&gt;less&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;--color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;always abc example.txt | less
ESC[01&lt;span class="p"&gt;;&lt;/span&gt;31mabcESC[00mdef
&lt;span class="o"&gt;(&lt;/span&gt;END&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the problem. If you pipe colorized output into a function like &lt;code&gt;less&lt;/code&gt; that doesn't know how to interpret it, the escape codes get treated as if they're regular ol' characters. Same thing happens if you're colorizing &lt;code&gt;ls&lt;/code&gt; or &lt;code&gt;grep&lt;/code&gt; in a terminal that doesn't support whatever escape codes you've set through &lt;code&gt;LSCOLORS&lt;/code&gt; or &lt;code&gt;GREP_COLOR&lt;/code&gt; variables (see this &lt;a href="https://unix.stackexchange.com/questions/143684/what-is-the-problem-with-the-output-of-plink"&gt;helpful post&lt;/a&gt; for a longer explanation).&lt;/p&gt;

&lt;p&gt;And that's what was happening to me in the &lt;a href="https://github.com/edeliver/edeliver"&gt;edeliver&lt;/a&gt; deploy script.&lt;/p&gt;

&lt;p&gt;Looking back at the &lt;a href="https://github.com/edeliver/edeliver/blob/master/libexec/erlang#L662"&gt;edeliver source code&lt;/a&gt;, the archived release file name is built from the output of &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt; commands. Because I had those colorization variables set in my &lt;code&gt;.bash_profile&lt;/code&gt;, my machine added the color escape codes to the output, which were "misinterpretted" as extra characters in the release archive filename, breaking the deploy.&lt;/p&gt;

&lt;p&gt;✋&lt;br&gt;&lt;br&gt;
.&lt;br&gt;&lt;br&gt;
.&lt;br&gt;&lt;br&gt;
.&lt;br&gt;&lt;br&gt;
🎤 ::mike drop::&lt;/p&gt;

&lt;h2 id="the-solution"&gt;The Solution&lt;/h2&gt;

&lt;p&gt;Remove any &lt;code&gt;ls&lt;/code&gt; or &lt;code&gt;grep&lt;/code&gt; color settings from your &lt;code&gt;.bash_profile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ☠️☠️☠️ incompatible with edeliver deploy script ☠️☠️☠️&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LSCOLORS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gxxxxxxxcxxxxxcxcxgxgx
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GREP_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--color=always'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GREP_COLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'4;38'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[update] Based on this &lt;a href="https://dev.to/carlfish/comment/35l8"&gt;helpful comment&lt;/a&gt; from &lt;a href="https://dev.to/carlfish"&gt;Charles Miller&lt;/a&gt;, even simpler solution is simply to change &lt;code&gt;export GREP_OPTIONS='--color=always'&lt;/code&gt; to &lt;code&gt;export GREP_OPTIONS='--color=auto'&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="learnings"&gt;Learnings&lt;/h2&gt;

&lt;p&gt;Debugging is hard, especially when you're working in a new codebase and/or new language. One thing that can really save you is good error messaging, something Elixir does well and &lt;a href="https://github.com/edeliver/edeliver/issues/80"&gt;edeliver can do better&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next steps from here will be to raise this issue for &lt;a href="https://github.com/edeliver/edeliver"&gt;edeliver&lt;/a&gt; and try to contribute some error message improvements (and maybe a fix for this escape sequence nonsense... think we'll just need to disable the color settings before running the deploy command).&lt;/p&gt;

&lt;h2 id="resources"&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/edeliver/edeliver#help"&gt;Official edeliver Debugging Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/ANSI_escape_code"&gt;More on ANSI escape codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/grep/manual/html_node/Environment-Variables.html"&gt;More on GNU &lt;code&gt;grep&lt;/code&gt; environment variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/edeliver/edeliver/issues/14"&gt;Similar issue reported on edeliver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/edeliver/edeliver/issues/80"&gt;More details on edeliver error messaging&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elixir</category>
      <category>edeliver</category>
      <category>deployment</category>
      <category>bash</category>
    </item>
  </channel>
</rss>
