<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Adam Albrecht</title>
  <link href="https://www.adamalbrecht.com/feed.xml" rel="self"/>
  <link href="https://www.adamalbrecht.com"/>
  <updated>2025-02-21T00:00:00+00:00</updated>
  <id>https://www.adamalbrecht.com</id>
  <author name="Adam Albrecht"/>
  <entry>
    <title>Home Cooked Apps</title>
    <link rel="alternate" href="https://www.robinsloan.com/notes/home-cooked-app/"/>
    <link rel="related" href="https://www.adamalbrecht.com/blog/2025/02/21/home-cooked-apps/"/>
    <id>https://www.adamalbrecht.com/blog/2025/02/21/home-cooked-apps/</id>
    <published>2025-02-21T00:00:00+00:00</published>
    <updated>2025-02-21T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;This article really spoke to me. I end up not building things all the time because I&amp;rsquo;m worried about product market fit, which tools to use to scale, etc. Instead, I need to lean into scratching my own itch and let it evolve however it may. Worst case scenario, I&amp;rsquo;ll build something useful for one person.&lt;/p&gt;

&lt;p&gt;The author&amp;rsquo;s favorite family communication app shut down, so he built his own.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It launched in the first week of January 2020, and almost immediately, it was downloaded by four people in three different time zones. In the years since, it has remained steady at four daily active users, with zero churn: a resounding success, exceeding every one of its creator&amp;rsquo;s expectations.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
  <entry>
    <title>Click Publish</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2025/02/20/click-publish/"/>
    <id>https://www.adamalbrecht.com/blog/2025/02/20/click-publish/</id>
    <published>2025-02-20T00:00:00+00:00</published>
    <updated>2025-02-20T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I&amp;rsquo;ve let this website atrophy a bit. Well, more than a bit. We&amp;rsquo;re coming up on 5 years since the last post - about as long as my oldest child has been alive and as long as I&amp;rsquo;ve been at my current job.&lt;/p&gt;

&lt;p&gt;Not to imply that parenting and work have kept me &lt;em&gt;so&lt;/em&gt; busy that I couldn&amp;rsquo;t write one measly blog post. But since that time, I&amp;rsquo;ve found myself less interested in writing the programming how-to&amp;rsquo;s that made up most of my past articles.&lt;/p&gt;

&lt;p&gt;Still, I &lt;em&gt;do&lt;/em&gt; want to write and share. I want this little corner of the internet to be a reflection of me.&lt;/p&gt;

&lt;p&gt;But I&amp;rsquo;ve been dragging my feet, unsure of where I want to take it. My &lt;code&gt;~/Code&lt;/code&gt; folder contains several half-hearted rewrites of the website itself, proof that I&amp;rsquo;ll do almost anything to avoid writing a handful of sentences.&lt;/p&gt;

&lt;p&gt;So today, I&amp;rsquo;m breaking the seal and clicking publish.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Add a Little Safety to your Elixir Structs with TypedStruct</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2020/04/06/add-a-little-safety-to-elixir-with-typedstruct/"/>
    <id>https://www.adamalbrecht.com/blog/2020/04/06/add-a-little-safety-to-elixir-with-typedstruct/</id>
    <published>2020-04-06T00:00:00+00:00</published>
    <updated>2020-04-06T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I&amp;rsquo;m working on an Elixir app at the moment and really enjoying it, but some of my recent dabbling in the type-safe worlds of &lt;a href="https://elm-lang.org"&gt;Elm&lt;/a&gt; and &lt;a href="https://crystal-lang.org"&gt;Crystal&lt;/a&gt; have left me desiring a bit more structure in my code. The app I&amp;rsquo;m building involves a multi-step data transformation and so I have a data structure to properly represent this process. But since Elixir is a dynamically typed language, you can&amp;rsquo;t, for example, have a non-nillable field in a struct. The Elixir/Erlang ecosystem does, however, have a type-checking syntax called &lt;a href="https://hexdocs.pm/elixir/typespecs.html"&gt;Type Specs&lt;/a&gt;, along with a tool, &lt;a href="http://erlang.org/doc/man/dialyzer.html"&gt;Dialyzer&lt;/a&gt;, that will find a fair number of errors at compile-time.&lt;/p&gt;

&lt;p&gt;But I found that using &lt;code&gt;defstruct&lt;/code&gt; with type specs to be fairly verbose and unintuitive. For example, let&amp;rsquo;s say you want a &amp;ldquo;Person&amp;rdquo; struct with the following attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name - string (non-nillable)&lt;/li&gt;
&lt;li&gt;Age - positive integer or nil&lt;/li&gt;
&lt;li&gt;Happy? - boolean (default to true)&lt;/li&gt;
&lt;li&gt;Phone - string or nil&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normally you&amp;rsquo;d do the following:&lt;/p&gt;
&lt;div class="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;Person&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="nv"&gt;@enforce_keys&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;name:&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;age:&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;happy?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="ss"&gt;phone:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;

  &lt;span class="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;t&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="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;name:&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;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;non_neg_integer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;happy?:&lt;/span&gt; &lt;span class="n"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="ss"&gt;phone:&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;t&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, the names of the keys and defaults are separate from the type information. This can get pretty hairy if you have a large, complex data structure and is very unintuitive if you aren&amp;rsquo;t already familiar with type specs. Luckily, I stumbled upon the &lt;a href="https://github.com/ejpcmac/typed_struct"&gt;TypedStruct&lt;/a&gt; package, which is a compile-time macro that dramatically improves the syntax. Using TypedStruct, the above example would look like this:&lt;/p&gt;
&lt;div class="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;Person&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;TypedStruct&lt;/span&gt;

  &lt;span class="n"&gt;typedstruct&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&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;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;enforce:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;non_neg_integer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:happy?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:phone&lt;/span&gt;&lt;span class="p"&gt;,&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;t&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;Now we&amp;rsquo;re talking! This is immediately understandable to anyone coming across it, particularly if you&amp;rsquo;re used to the DSL used to define schemas in &lt;a href="https://hexdocs.pm/ecto/Ecto.html"&gt;Ecto&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So then what happens when I use the struct improperly?&lt;/p&gt;
&lt;div class="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;PersonUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@spec&lt;/span&gt; &lt;span class="n"&gt;init_person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="no"&gt;Person&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="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init_person&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name:&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;age:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;happy?:&lt;/span&gt; &lt;span class="s2"&gt;"yes"&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;NeoVim, configured properly with &lt;a href="https://github.com/neoclide/coc.nvim"&gt;Coc.nvim&lt;/a&gt;, gives me a popup warning message:&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/images/elixir_dialyzer_vim_typed_struct-f7708aa9.png" alt="NeoVim Elixir Typespec Warning Message" /&gt;&lt;/p&gt;

&lt;p&gt;And VSCode, with the &lt;a href="https://marketplace.visualstudio.com/items?itemName=JakeBecker.elixir-ls"&gt;Elixir-LS&lt;/a&gt; extension, will do the same:&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/images/elixir_dialyzer_vscode_typed_struct-f3577a06.png" alt="VSCode Elixir Typespec Warning Message" /&gt;&lt;/p&gt;

&lt;p&gt;In an ideal world, the program wouldn&amp;rsquo;t compile. But this is still a huge help, particularly in a large codebase that you&amp;rsquo;re not completely familiar with.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Upcoming Phoenix Authentication Solution</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2020/04/02/upcoming-phoenix-auth-framework-generator/"/>
    <id>https://www.adamalbrecht.com/blog/2020/04/02/upcoming-phoenix-auth-framework-generator/</id>
    <published>2020-04-02T00:00:00+00:00</published>
    <updated>2020-04-02T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I&amp;rsquo;m in the middle of writing an application in &lt;a href="https://elixir-lang.org"&gt;Elixir&lt;/a&gt; and &lt;a href="https://www.phoenixframework.org"&gt;Phoenix&lt;/a&gt;, so when I saw a link to &lt;a href="https://dashbit.co/blog/a-new-authentication-solution-for-phoenix"&gt;an article by José Valim&lt;/a&gt; on an upcoming authentication solution for Phoenix, my initial reaction (before reading it) was negative. José is the author of the &lt;a href="https://github.com/plataformatec/devise"&gt;Devise framework&lt;/a&gt; for Ruby-on-Rails, so I assumed it was going to be the same idea, but for Elixir and Phoenix. I&amp;rsquo;ve implemented Devise in a handful of Rails apps, and each and every time I ended up ripping it out and writing my own auth solution (often based on &lt;a href="http://railscasts.com/episodes/250-authentication-from-scratch-revised"&gt;this Railscasts tutorial&lt;/a&gt;). The reason is that while authentication works similarly in most apps, there are always 1 or 2 business requirements that fall outside of what Devise can do in a simple and straightforward manner. Yes, Devise is very flexible there are hooks to add logic and a number of extensions available, but that makes for code that is hard to follow and understand. And something as crucial as authentication needs to be well understood by the maintainers of any web application.&lt;/p&gt;

&lt;p&gt;But to my great satisfaction, José said exactly this!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While this made Devise more flexible and general purpose, it also made it more complex. A complex codebase is harder to be audited, which is important in authentication systems. Furthermore, the existence of too many options and customization hooks makes it extremely hard to guarantee that the authentication system will continue be secure under all possible customization combinations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;His authentication &amp;ldquo;solution&amp;rdquo; is not a framework, but a code generator. It gets you started with the basic code you need to roll your own authentication. It&amp;rsquo;s not finished yet, but I&amp;rsquo;ve looked over the code and it&amp;rsquo;s &lt;em&gt;exactly&lt;/em&gt; what I&amp;rsquo;ve been wanting for Phoenix. It will make spinning up a new app dramatically simpler. 👏&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>JavaScript Sprinkles with AlpineJS</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2020/03/24/javascript-sprinkles-with-alpinejs/"/>
    <id>https://www.adamalbrecht.com/blog/2020/03/24/javascript-sprinkles-with-alpinejs/</id>
    <published>2020-03-24T00:00:00+00:00</published>
    <updated>2020-03-24T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I&amp;rsquo;m a big of &lt;a href="https://reactjs.org"&gt;ReactJS&lt;/a&gt;, but sometimes it is way too heavy for what I need. The majority of the applications I create are server-rendered and just need some &amp;ldquo;sprinkles&amp;rdquo; of JavaScript. In the past, I&amp;rsquo;ve leaned on &lt;a href="https://jquery.com"&gt;jQuery&lt;/a&gt; for this, but I&amp;rsquo;m not a fan of the imperative nature of it.&lt;/p&gt;

&lt;p&gt;Recently, I stumbled upon AlpineJS, which is a super minimalist framework that lets you write declarative sprinkles of JavaScript without resorting to something heavier like React or &lt;a href="https://vuejs.org"&gt;Vue&lt;/a&gt;. It comes in at just 6.4kb (compressed), less than a quarter of the size of Vue, React, or jQuery. And everything is done inline within your HTML, so, like React, your logic is co-located with your markup. Unlike React and Vue, AlpineJS does not use a virtual DOM and relies and the actual DOM.&lt;/p&gt;

&lt;p&gt;So for a dead simple example, let&amp;rsquo;s say you wanted a button that toggled a piece of content. You use the &lt;code&gt;x-data&lt;/code&gt; attribute to declare your component scope and initial data, &lt;code&gt;x-show&lt;/code&gt; to toggle your content, and &lt;code&gt;x-on:click&lt;/code&gt; to add the click behavior.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;x-data=&lt;/span&gt;&lt;span class="s"&gt;"{isOpen: false}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;x-on:click=&lt;/span&gt;&lt;span class="s"&gt;"isOpen = true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Show Content&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;x-show=&lt;/span&gt;&lt;span class="s"&gt;"isOpen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Content goes here.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&amp;rsquo;s it! Simple and easy to follow. If we wanted to add a little pizazz, we could use &lt;code&gt;x-show.transition&lt;/code&gt; instead and this will animate our content when it&amp;rsquo;s shown and hidden.&lt;/p&gt;

&lt;p&gt;My only real complaint with this, which is the same complaint I have about Angular (1.x) and Vue, is the placement of logic inside strings. The programming purist in me is not a fan of this, but I know it makes sense from a practical standpoint given the historical baggage of HTML.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s move on to a slightly more complex example. Here we&amp;rsquo;ll keep the value of a text input in sync with the text in a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tag. The &lt;code&gt;x-model&lt;/code&gt; attribute is used for input 2-way binding and &lt;code&gt;x-text&lt;/code&gt; is used for outputting the variable.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;x-data=&lt;/span&gt;&lt;span class="s"&gt;"{fullName: ''}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Full Name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;x-model=&lt;/span&gt;&lt;span class="s"&gt;"fullName"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;x-text=&lt;/span&gt;&lt;span class="s"&gt;'fullName'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But let&amp;rsquo;s say we want to prefix the name with &amp;ldquo;My name is&amp;rdquo; and only show it when the name has been filled in. We&amp;rsquo;ll use the &lt;code&gt;x-if&lt;/code&gt; attribute on a &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;x-data=&lt;/span&gt;&lt;span class="s"&gt;"{fullName: ''}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Full Name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;x-model=&lt;/span&gt;&lt;span class="s"&gt;"fullName"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;x-if=&lt;/span&gt;&lt;span class="s"&gt;"fullName.length &amp;gt; 0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;x-text=&lt;/span&gt;&lt;span class="s"&gt;'fullName'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lastly, let&amp;rsquo;s do about as complex of an example as I&amp;rsquo;d recommend with Alpine. We&amp;rsquo;ll loop over an array of users and display them in a table along with a form to add another user.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;x-data=&lt;/span&gt;&lt;span class="s"&gt;"{newUser: { name: '', age: 10 }, users: [{name: 'John', age: 30}, {name: 'Mary', age: 40}]}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Age&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;x-for=&lt;/span&gt;&lt;span class="s"&gt;"user in users"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"users"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;x-text=&lt;/span&gt;&lt;span class="s"&gt;"user.name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;x-text=&lt;/span&gt;&lt;span class="s"&gt;"user.age"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text'&lt;/span&gt; &lt;span class="na"&gt;x-model=&lt;/span&gt;&lt;span class="s"&gt;'newUser.name'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;'age'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Age&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'age'&lt;/span&gt; &lt;span class="na"&gt;x-model=&lt;/span&gt;&lt;span class="s"&gt;'newUser.age'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'10'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;10&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'20'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;20&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'30'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;30&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'40'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;40&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'50'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;50&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'60'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;60&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'70'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;70&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'80'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;80&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'90'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;90&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'100'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;100&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;x-on:click=&lt;/span&gt;&lt;span class="s"&gt;"users.push(newUser); newUser = {name: '', age: 10};"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Add User&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Like I said, this is about as complex as you&amp;rsquo;d want to get with Alpine. But I think that&amp;rsquo;s a feature, not a bug. Sometimes when you use something as powerful as React or Vue, it&amp;rsquo;s tempting to push more and more of your app into that paradigm, all while forgetting that there are rough edges around doing so.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Enable Spell Checking in Vim for Markdown and Git Commit Messages</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/10/21/spell-check-in-vim-for-markdown-and-git-commit-messages/"/>
    <id>https://www.adamalbrecht.com/blog/2019/10/21/spell-check-in-vim-for-markdown-and-git-commit-messages/</id>
    <published>2019-10-21T00:00:00+00:00</published>
    <updated>2019-10-21T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I had a ridiculous typo in a Git commit message recently, so I decided to explore spell checking in Vim. As it turns out, it&amp;rsquo;s extremely easy.&lt;/p&gt;

&lt;p&gt;I only wanted it enabled for Git commit messages and markdown, so I added the following to my vimrc / init.vim:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" Spell-check Markdown files and Git Commit Messages&lt;/span&gt;
autocmd &lt;span class="nb"&gt;FileType&lt;/span&gt; markdown &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;spell&lt;/span&gt;
autocmd &lt;span class="nb"&gt;FileType&lt;/span&gt; gitcommit &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;spell&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By doing this, it highlights potential misspellings in red underline. You can see a list of potential corrections by moving the cursor over the word in normal mode and pressing &lt;code&gt;z=&lt;/code&gt;. Or you can add the word to the dictionary by pressing &lt;code&gt;zg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While trying this out, I also discovered that you can enable dictionary auto-completion using Vim&amp;rsquo;s normal &lt;code&gt;ctrl-n&lt;/code&gt; and &lt;code&gt;ctrl-p&lt;/code&gt;. To enable this (again, for select file types), add the following to your vimrc / init.vim:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" Enable dictionary auto-completion in Markdown files and Git Commit Messages&lt;/span&gt;
autocmd &lt;span class="nb"&gt;FileType&lt;/span&gt; markdown &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;+=&lt;/span&gt;kspell
autocmd &lt;span class="nb"&gt;FileType&lt;/span&gt; gitcommit &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;+=&lt;/span&gt;kspell
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, while in insert mode, type part of a word and hit &lt;code&gt;ctrl-n&lt;/code&gt; to start cycling through potential matches and &lt;code&gt;ctrl-p&lt;/code&gt; to cycle through in reverse.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a quick demonstration of both spell check and dictionary auto completion:&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/images/vim_spell_check_and_dictionary_auto_complete-1155dd19.gif" alt="Vim Spell-Checking and Auto Complete" /&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Dark Mode and other site updates</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/10/20/dark-mode-and-other-site-updates/"/>
    <id>https://www.adamalbrecht.com/blog/2019/10/20/dark-mode-and-other-site-updates/</id>
    <published>2019-10-20T00:00:00+00:00</published>
    <updated>2019-10-20T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;Inspired by iOS&amp;rsquo;s new dark mode (and halloween!), I decided to a dark mode to the website using the new &lt;code&gt;prefers-color-scheme&lt;/code&gt; media query. It was surprisingly easy to do. After I&amp;rsquo;d changed the &lt;/p&gt;

&lt;p&gt;This took care of 90% of it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#19222b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.page-wrapper__inner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#222f3b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&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;Using a straight black-and-white background and foreground combo looks too harsh on the eyes, so you want to find a gray-ish background. Mine is a bluish-grayish color that matched well with some of the existing highlight colors on the site.&lt;/p&gt;

&lt;p&gt;Then it was a matter of browsing through the site and finding UI elements that didn&amp;rsquo;t look right. It took me less than 30 minutes in total.&lt;/p&gt;

&lt;p&gt;Also, I decided to merge my blog, which was split into &amp;ldquo;articles&amp;rdquo; and &amp;ldquo;work journal&amp;rdquo; entries, back together. It was more trouble than it was worth. Sorry if this messed up the RSS feed.&lt;/p&gt;

&lt;p&gt;In case you&amp;rsquo;re on an OS or browser that doesn&amp;rsquo;t support &lt;code&gt;prefers-color-scheme&lt;/code&gt;, here&amp;rsquo;s a screenshot:&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/images/adam_albrecht_dot_com_dark_mode-2e810926.png" alt="Screenshot of Dark Mode on my website" /&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Quickly Convert 4 Spaces (or Tabs) to 2 spaces in Vim</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/10/19/convert-4-spaces-or-tabs-to-2-spaces-in-vim/"/>
    <id>https://www.adamalbrecht.com/blog/2019/10/19/convert-4-spaces-or-tabs-to-2-spaces-in-vim/</id>
    <published>2019-10-19T00:00:00+00:00</published>
    <updated>2019-10-19T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;Here&amp;rsquo;s a handy Vim command that I find myself searching for often. It could easily be made into a function in your vimrc.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" 4 spaces to 2 spaces&lt;/span&gt;
%s;^\&lt;span class="p"&gt;(&lt;/span&gt;\s\&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="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;submatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;/&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;;&lt;span class="k"&gt;g&lt;/span&gt;

&lt;span class="c"&gt;" Tab to 2 spaces&lt;/span&gt;
%s&lt;span class="sr"&gt;/\t/&lt;/span&gt;  /&lt;span class="k"&gt;g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Get the Previous Expression Value in IEx</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/09/09/v-helper-function-in-elixir-iex/"/>
    <id>https://www.adamalbrecht.com/blog/2019/09/09/v-helper-function-in-elixir-iex/</id>
    <published>2019-09-09T00:00:00+00:00</published>
    <updated>2019-09-09T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;When using Elixir, I&amp;rsquo;ve long missed the special &lt;code&gt;_&lt;/code&gt; helper from &lt;a href="https://en.wikipedia.org/wiki/Interactive_Ruby_Shell"&gt;irb&lt;/a&gt; that returns the result of the previous expression. Sometimes I actually type it out of pure habit.&lt;/p&gt;

&lt;p&gt;Little did I know that Elixir has the same thing, except better.&lt;/p&gt;

&lt;p&gt;IEx.Helpers has a function &lt;code&gt;v(n \\ -1)&lt;/code&gt; that returns  the value of the nth expression in the session history. So &lt;code&gt;v&lt;/code&gt; alone returns the previous expression and &lt;code&gt;v(-2)&lt;/code&gt; returns the one before it.&lt;/p&gt;
&lt;div class="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="s2"&gt;"abc"&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="s2"&gt;"zyx"&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;v&lt;/span&gt;
&lt;span class="s2"&gt;"zyx"&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;v&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"abc"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Ruby Symbol and String Array Shorthand</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/08/27/ruby-symbol-and-string-array-shorthand/"/>
    <id>https://www.adamalbrecht.com/blog/2019/08/27/ruby-symbol-and-string-array-shorthand/</id>
    <published>2019-08-27T00:00:00+00:00</published>
    <updated>2019-08-27T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;Ruby has some handy Array shorthands, but I always forget which is which, so I thought I should write them down.&lt;/p&gt;

&lt;h3 id="symbol-array-shorthand"&gt;Symbol Array Shorthand:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="sx"&gt;%i{foo bar}&lt;/span&gt;  &lt;span class="c1"&gt;# =&amp;gt; [:foo, :bar]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="string-array-shorthand"&gt;String Array Shorthand:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="sx"&gt;%w{foo bar}&lt;/span&gt;  &lt;span class="c1"&gt;# =&amp;gt; ["foo", "bar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both also work with square brackets &lt;code&gt;%w[a b c]&lt;/code&gt; or parenthesis &lt;code&gt;%i(a b c)&lt;/code&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Running Elixir tests in VSCode</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/30/running-elixir-tests-in-vscode/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/30/running-elixir-tests-in-vscode/</id>
    <published>2019-07-30T00:00:00+00:00</published>
    <updated>2019-07-30T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;In Vim-land, I use the &lt;a href="https://www.github.com/janko-m/vim-test"&gt;vim-test plugin&lt;/a&gt; for quickly executing tests from a command line shortcut&lt;sup id="fnref1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;. I wanted to reproduce this behavior in &lt;a href="https://code.visualstudio.com"&gt;Visual Studio Code&lt;/a&gt;, but I couldn&amp;rsquo;t find an extension that worked in multiple languages (namely, Ruby, Elixir, Javascript, and Elm). I&amp;rsquo;m mostly just using VSCode for Elixir, but I still liked the idea of finding a more general purpose solution.&lt;/p&gt;

&lt;p&gt;So instead I used VSCode&amp;rsquo;s support for &lt;a href="https://code.visualstudio.com/docs/editor/tasks"&gt;Tasks&lt;/a&gt; to build the functionality myself. So in my project&amp;rsquo;s &lt;code&gt;tasks.json&lt;/code&gt; file, I have the following 3 tasks for running all tests, a single test (whatever is under the cursor), and the current file&amp;rsquo;s tests.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mix test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mix test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"focus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"panel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shared"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"clear"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"single test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mix test ${relativeFile}:${lineNumber}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"focus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"panel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shared"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"clear"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"runOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reevaluateOnRerun"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test current file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mix test ${relativeFile}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"focus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"panel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shared"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"clear"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"runOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reevaluateOnRerun"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, I setup keyboard shortcuts to run these. You can access this json file by going to Preferences &amp;ndash;&amp;gt; Keyboard Shortcuts, and then clicking the &lt;code&gt;{}&lt;/code&gt; icon. I used &lt;code&gt;alt-t&lt;/code&gt; and &lt;code&gt;alt-shift-t&lt;/code&gt; for single test and current file, respectively. I didn&amp;rsquo;t create one for running all of the tests because I don&amp;rsquo;t do that frequently enough to warrant a shortcut.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alt+t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workbench.action.tasks.runTask"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"single test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"editorLangId == elixir"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alt+shift+t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workbench.action.tasks.runTask"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test current file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"editorLangId == elixir"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="footnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="/articles/2016/02/01/run-your-ruby-tests-using-vim-and-tmux"&gt;I have an article about this&lt;/a&gt;, but my setup has since changed to use this plugin instead.&amp;nbsp;&lt;a href="#fnref1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  <entry>
    <title>SSH Tunnels into Production Rails Database</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/25/ssh-tunnel-into-rails-production-database/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/25/ssh-tunnel-into-rails-production-database/</id>
    <published>2019-07-25T00:00:00+00:00</published>
    <updated>2019-07-25T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;Today I needed to access a production database for my Rails app directly using a GUI application on my mac, so I figured out that this can be done by creating an SSH tunnel like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-Ng&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; &amp;lt;local-port&amp;gt;:&amp;lt;remote-host&amp;gt;:&amp;lt;remote-port&amp;gt; &amp;lt;user&amp;gt;@&amp;lt;remote-host&amp;gt;
ssh &lt;span class="nt"&gt;-Ng&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 3307:100.64.26.11:3307 adam@100.64.26.11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then, in your Rails app, update the database.yml as if you were connecting to a local database,
but specify the proper database name.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql2&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp_production&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3307&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secret&lt;/span&gt;
  &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utf8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Rails presence method</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/24/rails-presence-method/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/24/rails-presence-method/</id>
    <published>2019-07-24T00:00:00+00:00</published>
    <updated>2019-07-24T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I use Rails&amp;rsquo; &lt;code&gt;present?&lt;/code&gt; method constantly, but recently I stumbled across the &lt;code&gt;presence&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;In the past, I have often found myself doing the following because params[:foo] could be nil or a blank string.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"something else"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I hate that i have to write &lt;code&gt;params[:foo]&lt;/code&gt; twice. But the &lt;code&gt;presence&lt;/code&gt; method is handy for this case. It returns nil if the item is nil or a blank string, but otherwise returns the value.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;presence&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"something-else"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>VSCode + ElixirLS = 👍👍</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/24/vscode-elixirls/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/24/vscode-elixirls/</id>
    <published>2019-07-24T00:00:00+00:00</published>
    <updated>2019-07-24T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I&amp;rsquo;ve played around with &lt;a href="https://code.visualstudio.com"&gt;VSCode&lt;/a&gt; here and there, but as a fairly picky Vim user who doesn&amp;rsquo;t do TypeScript, I never quite understood the hype.&lt;/p&gt;

&lt;p&gt;Today I started up a new Elixir / Phoenix project (more on that to come) and tried out the &lt;a href="https://github.com/JakeBecker/vscode-elixir-ls"&gt;Elixir Language Server Extension&lt;/a&gt; and the integration is &lt;strong&gt;very&lt;/strong&gt; impression. Code completion, debugger support, automatic inference of Dialyzer &lt;a href="https://hexdocs.pm/elixir/typespecs.html"&gt;Typespecs&lt;/a&gt;, documentation on hover, and more&amp;hellip;.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t expect to be using VSCode as my standard editor (again, picky Vim user&lt;sup id="fnref1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;), but I think I&amp;rsquo;ll stick with it on Elixir projects.&lt;/p&gt;

&lt;div class="footnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;The &lt;a href="https://github.com/VSCodeVim/Vim"&gt;vim-mode extension&lt;/a&gt; has improved dramatically, but still not quite like the real thing &amp;nbsp;&lt;a href="#fnref1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  <entry>
    <title>Netlify Analytics First Impressions</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/23/netlify-analytics-quick-review/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/23/netlify-analytics-quick-review/</id>
    <published>2019-07-23T00:00:00+00:00</published>
    <updated>2019-07-23T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;My new website is hosted on &lt;a href="https://www.netlify.com"&gt;Netlify&lt;/a&gt;, which is an &lt;strong&gt;awesome&lt;/strong&gt; service for hosting static websites. Recently, &lt;a href="https://www.netlify.com/blog/2019/07/10/netlify-analytics---accurate-insights-without-performance-impacts/"&gt;they launched an Analytics Platform&lt;/a&gt; as an alternative to Google Analytics. My impressions of this new tool isn&amp;rsquo;t quite as enthusiastic as their service in general, but it does have some nice features.&lt;/p&gt;

&lt;div style='text-align:center; margin-bottom: 1rem'&gt;
&lt;img src='/assets/images/netlify_analytics_screenshot.png' alt='Netlify Analytics Screenshot' /&gt;
&lt;/div&gt;

&lt;h3 id="pros"&gt;Pros:&lt;/h3&gt;

&lt;h5 id="server-side"&gt;Server Side&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Can&amp;rsquo;t be blocked by Ad-Blockers&lt;/li&gt;
&lt;li&gt;Tracks requests of non-web-page assets like RSS feeds, images, etc&lt;/li&gt;
&lt;li&gt;No impact on your client side performance since there&amp;rsquo;s no Javascript library&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id="privacy-centric"&gt;Privacy Centric&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Isn&amp;rsquo;t connected to an ad network that&amp;rsquo;s building a database of what sites you&amp;rsquo;re browsing&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h3 id="cons"&gt;Cons:&lt;/h3&gt;

&lt;h5 id="server-side"&gt;Server Side&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;You can&amp;rsquo;t track any user behavior via Javascript. I never do this anyway, but many sites do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id="extremely-barebones"&gt;Extremely barebones&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;No way to filter users by geography, browser, OS, etc&lt;/li&gt;
&lt;li&gt;No way to exclude people by IP address. I generally like to exclude my house and my office.&lt;/li&gt;
&lt;li&gt;No way to track conversions / goals&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id="expensive"&gt;Expensive!&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;$9/month is expensive for such a barebones feature set. Particular when compared to $0 for Google Analytics.&lt;/li&gt;
&lt;li&gt;This is somewhat mitigated for me by the fact that my site falls under the free tier of their hosting service.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h3 id="conclusion"&gt;Conclusion:&lt;/h3&gt;

&lt;p&gt;I like the general premise of Netlify Analytics, but given the lack of features and price, I suspect that I&amp;rsquo;ll cancel it off after a month or two. But I&amp;rsquo;d wager that this is just the MVP for what will eventually become a much more comprehensive tool. So perhaps check back in a year.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>TIL: Pass in an ActiveRecord Object to a where string</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/22/pass-in-an-active-record-object-to-a-where-string-in-rails/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/22/pass-in-an-active-record-object-to-a-where-string-in-rails/</id>
    <published>2019-07-22T00:00:00+00:00</published>
    <updated>2019-07-22T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I&amp;rsquo;m surprised I didn&amp;rsquo;t already know this, but if you have an ActiveRecord &lt;code&gt;where&lt;/code&gt; statement that references an id column, you can just pass in an object and it will pass in the object&amp;rsquo;s id, not the string representation of the object.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"users.company_id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# is equal to&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"users.company_id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So when you create named scopes, you don&amp;rsquo;t have to do the song-and-dance where you check to see if the object is a model or an integer, as shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:by_company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;
    &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s2"&gt;"users.company_id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;company_id&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="c1"&gt;# You wouldn't actually want to use a string in this example.&lt;/span&gt;
&lt;span class="c1"&gt;# Try to only use strings in very complex scopes and queries.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Lookup IP Address &amp; Location via the Command Line</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/21/lookup-ip-address-location-via-the-command-line/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/21/lookup-ip-address-location-via-the-command-line/</id>
    <published>2019-07-21T00:00:00+00:00</published>
    <updated>2019-07-21T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;With &lt;a href="https://ifconfig.co"&gt;ifconfig.co&lt;/a&gt;, you can lookup your external IP Address and Location Information using a simple curl command. You can use it like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl ifconfig.co/json
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"ip"&lt;/span&gt;: &lt;span class="s2"&gt;"96.27.202.202"&lt;/span&gt;,
  &lt;span class="s2"&gt;"ip_decimal"&lt;/span&gt;: 1612409628,
  &lt;span class="s2"&gt;"country"&lt;/span&gt;: &lt;span class="s2"&gt;"United States"&lt;/span&gt;,
  &lt;span class="s2"&gt;"country_iso"&lt;/span&gt;: &lt;span class="s2"&gt;"US"&lt;/span&gt;,
  &lt;span class="s2"&gt;"city"&lt;/span&gt;: &lt;span class="s2"&gt;"Columbus"&lt;/span&gt;,
  &lt;span class="s2"&gt;"hostname"&lt;/span&gt;: &lt;span class="s2"&gt;"d27-96-101-101.nap.wideopenwest.com"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;curl ifconfig.co/city
Columbus

&lt;span class="nv"&gt;$ &lt;/span&gt;curl ifconfig.co/country
United States
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Website Revamp! And introduction to my Work Journal.</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2019/07/20/new-website-and-work-journal-introduction/"/>
    <id>https://www.adamalbrecht.com/blog/2019/07/20/new-website-and-work-journal-introduction/</id>
    <published>2019-07-20T00:00:00+00:00</published>
    <updated>2019-07-20T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;My website has gone slightly stagnent lately, so I decided that it was time for a revamp. There were a few things I didn&amp;rsquo;t like about the old website:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a developer with some design chops, I never liked the fact that I hadn&amp;rsquo;t designed my website myself. I was using the &lt;a href="http://hyde.getpoole.com"&gt;Hyde theme for Jekyll&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I felt boxed in by the fact that all my previous posts were longer-form articles.&lt;/li&gt;
&lt;li&gt;While &lt;a href="https://jekyllrb.com"&gt;Jekyll&lt;/a&gt; is a great tool, it&amp;rsquo;s very blogging-centric, and I wanted to add new types of content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I re-designed the website from scratch using &lt;a href="http://middlemanapp.com"&gt;Middleman&lt;/a&gt;. I started with &lt;a href="https://github.com/thoughtbot/middleman-template"&gt;Thoughtbot&amp;rsquo;s base Middleman template&lt;/a&gt;, but I changed quite a bit from there. And all the design is custom. I&amp;rsquo;m pretty happy with the result. And finally, I added a &amp;ldquo;Work Journal&amp;rdquo;, where I plan to write shorter, more informal posts on what&amp;rsquo;s going on in my work. That could be something I learned, a book I just read, a status update on a side project, etc.&lt;/p&gt;

&lt;p&gt;Exciting things to come!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Run your Ruby tests quickly and easily using Vim and Tmux</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2016/02/01/run-your-ruby-tests-using-vim-and-tmux/"/>
    <id>https://www.adamalbrecht.com/blog/2016/02/01/run-your-ruby-tests-using-vim-and-tmux/</id>
    <published>2016-02-01T00:00:00+00:00</published>
    <updated>2016-02-01T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;In order for testing to become part of your development workflow, it needs to become a habit. And like any habit, its biggest enemy is neglect. Too often I&amp;rsquo;ll be in a rush and not add tests to my code for a day, and that turns into a week and then a month, and suddenly I have an app where half of my codebase is untested and the other half has breaking tests. There are many things you can do to help keep this habit (hooking up a CI server immediately comes to mind), but an important one is to make running your tests as quick and easy as possible.&lt;/p&gt;

&lt;p&gt;One way I do this is by making my ruby tests (either Rspec or Minitest) extremely easy to run while I&amp;rsquo;m using &lt;a href="http://www.vim.org"&gt;Vim&lt;/a&gt; (and &lt;a href="https://tmux.github.io"&gt;Tmux&lt;/a&gt;). With one quick keystroke, I can run the current test file or individual test in a new Tmux pane.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To set this up, first install the following 2 Vim plugins using a plugin manager such as &lt;a href="https://github.com/Shougo/neobundle.vim"&gt;NeoBundle&lt;/a&gt; or &lt;a href="https://github.com/VundleVim/Vundle.vim"&gt;Vundle&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/benmills/vimux"&gt;Vimux&lt;/a&gt;: Enables Vim to interact with Tmux&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jgdavey/vim-turbux"&gt;Turbux&lt;/a&gt;: Run ruby tests from Vim&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, you&amp;rsquo;ll probably want to configure your test command to be prefixed with &lt;code&gt;bundle exec&lt;/code&gt;, so add the following to your Vimrc:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:turbux_command_prefix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'bundle exec'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that everything is installed (and you&amp;rsquo;ve reloaded Vim if needed), you can open your first test file. Then just hit &lt;code&gt;&amp;lt;leader&amp;gt; t&lt;/code&gt; to run all of the tests. It will then open up a new tmux pane (or reuse an existing one if already open) and run them just as if you had run the command yourself. And then if you want to run a single test at a time, move the cursor to inside the test and hit &lt;code&gt;&amp;lt;leader&amp;gt; T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can change these default keyboard shortcuts if you&amp;rsquo;d like. Here&amp;rsquo;s what I use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:no_turbux_mappings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;t&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Plug&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SendTestToTmux
&lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;s &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Plug&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SendFocusedTestToTmux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By combining these handy shortcuts with the speed increase provided by &lt;a href="http://guides.rubyonrails.org/4_1_release_notes.html#spring-application-preloader"&gt;Spring&lt;/a&gt;, the application preloader added in Rails 4.1, you&amp;rsquo;ll have no excuse not to be running your tests quickly and frequently.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a quick gif of how the whole process looks:&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/images/vim_tmux_testing-9485262f.gif" alt="Demo of running mintest from Vim and Tmux" /&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Authentication with JSON Web Tokens using Rails and React / Flux</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2015/07/20/authentication-using-json-web-tokens-using-rails-and-react/"/>
    <id>https://www.adamalbrecht.com/blog/2015/07/20/authentication-using-json-web-tokens-using-rails-and-react/</id>
    <published>2015-07-20T00:00:00+00:00</published>
    <updated>2015-07-20T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;In a &lt;a href="/2014/12/04/add-json-web-token-authentication-to-your-angular-rails-app"&gt;previous post&lt;/a&gt;, I went over how to add authentication to your Rails + Angular app using JSON Web Tokens (JWT). This time, I&amp;rsquo;ll do the same, but using the &lt;a href="2015/07/17/how-to-replace-the-angular-stack-with-the-react-ecosystem"&gt;React ecosystem&lt;/a&gt;. But even if you&amp;rsquo;re using another front-end framework (Angular, Ember, Backbone), this post will be helpful because it fixes some issues with the previous server-side code that broke due to a change in the &lt;a href="https://github.com/progrium/ruby-jwt"&gt;jwt gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;As I mentioned last time, I am a huge proponent of rolling your own authentication. It is not particularly complicated, plus I have found that the flexibility of a custom solution almost always comes in handy down the road and more than makes up for the up-front time-savings.&lt;/p&gt;

&lt;p&gt;Before getting started, you should go back and read the first 2 sections (Overview and Client/Server Data Flow) of the &lt;a href="/2014/12/04/add-json-web-token-authentication-to-your-angular-rails-app"&gt;previous post&lt;/a&gt; because I&amp;rsquo;m not going to repeat this information. Also, this tutorial assumes you already have a user model that includes a username and password.&lt;/p&gt;

&lt;h2 id="server-side"&gt;Server Side&lt;/h2&gt;

&lt;p&gt;To get started, you&amp;rsquo;ll first need to install the &lt;a href="https://github.com/progrium/ruby-jwt"&gt;jwt&lt;/a&gt; gem.&lt;/p&gt;

&lt;p&gt;Next, let&amp;rsquo;s create a very simple abstraction for encoding and decoding auth tokens. So let&amp;rsquo;s create a file at &lt;code&gt;lib/auth_token.rb&lt;/code&gt; and add the following code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthToken&lt;/span&gt;
  &lt;span class="c1"&gt;# Encode a hash in a json web token&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl_in_minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:exp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ttl_in_minutes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
    &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Decode a token and return the payload inside&lt;/span&gt;
  &lt;span class="c1"&gt;# If will throw an error if expired or invalid. See the docs for the JWT gem.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;leeway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;leeway: &lt;/span&gt;&lt;span class="n"&gt;leeway&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;HashWithIndifferentAccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;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 code is fairly straightforward. Note that the &lt;code&gt;decode&lt;/code&gt; method could potentially raise on of several exceptions, so any calling code should account for this.&lt;/p&gt;

&lt;p&gt;Next, we need to implement the endpoint used by our login form. So create a new controller called &lt;code&gt;AuthController&lt;/code&gt; with a single &lt;code&gt;authenticate&lt;/code&gt; action. What it will do is verify the username and password and, if correct, create a new auth token that the client can then use to make authenticated requests. We implemented the &lt;code&gt;authentication_payload&lt;/code&gt; method separately because we&amp;rsquo;re going to reuse it later.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;
    &lt;span class="c1"&gt;# You'll need to implement the below method. It should return the&lt;/span&gt;
    &lt;span class="c1"&gt;# user instance if the username and password are valid.&lt;/span&gt;
    &lt;span class="c1"&gt;# Otherwise return nil.&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by_credentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:password&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="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="n"&gt;authentication_payload&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;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;errors: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Invalid username or password'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :unauthorized&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authentication_payload&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;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;id&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;auth_token: &lt;/span&gt;&lt;span class="no"&gt;AuthToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="ss"&gt;user: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;id: &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;id&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;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="c1"&gt;# return whatever user info you need&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 add a route to your &lt;code&gt;routes.rb&lt;/code&gt; file to make it accessible:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'authenticate'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'auth#authenticate'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, we need a way to authenticate each request and also find out who the current user is. We&amp;rsquo;ll add this code to our &lt;code&gt;ApplicationController&lt;/code&gt;, exposing &lt;code&gt;authenticate_request!&lt;/code&gt; and &lt;code&gt;current_user&lt;/code&gt; methods to the rest of our controllers.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccessDeniedError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotAuthenticatedError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationTimeoutError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;API&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:current_user&lt;/span&gt;

  &lt;span class="c1"&gt;# When an error occurs, respond with the proper private method below&lt;/span&gt;
  &lt;span class="n"&gt;rescue_from&lt;/span&gt; &lt;span class="no"&gt;AuthenticationTimeoutError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: :authentication_timeout&lt;/span&gt;
  &lt;span class="n"&gt;rescue_from&lt;/span&gt; &lt;span class="no"&gt;NotAuthenticatedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: :user_not_authenticated&lt;/span&gt;

  &lt;span class="kp"&gt;protected&lt;/span&gt;

  &lt;span class="c1"&gt;# This method gets the current user based on the user_id included&lt;/span&gt;
  &lt;span class="c1"&gt;# in the Authorization header (json web token).&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# Call this from child controllers in a before_action or from&lt;/span&gt;
  &lt;span class="c1"&gt;# within the action method itself&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate_request!&lt;/span&gt;
    &lt;span class="nb"&gt;fail&lt;/span&gt; &lt;span class="no"&gt;NotAuthenticatedError&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;user_id_included_in_auth_token?&lt;/span&gt;
    &lt;span class="vi"&gt;@current_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded_auth_token&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ExpiredSignature&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;AuthenticationTimeoutError&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;VerificationError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;DecodeError&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotAuthenticatedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="c1"&gt;# Authentication Related Helper Methods&lt;/span&gt;
  &lt;span class="c1"&gt;# ------------------------------------------------------------&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_id_included_in_auth_token?&lt;/span&gt;
    &lt;span class="n"&gt;http_auth_token&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;decoded_auth_token&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;decoded_auth_token&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Decode the authorization header token and return the payload&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decoded_auth_token&lt;/span&gt;
    &lt;span class="vi"&gt;@decoded_auth_token&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;AuthToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http_auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Raw Authorization Header token (json web token format)&lt;/span&gt;
  &lt;span class="c1"&gt;# JWT's are stored in the Authorization header using this format:&lt;/span&gt;
  &lt;span class="c1"&gt;# Bearer somerandomstring.encoded-payload.anotherrandomstring&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;http_auth_token&lt;/span&gt;
    &lt;span class="vi"&gt;@http_auth_token&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Authorization'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
                           &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Authorization'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;last&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;# Helper Methods for responding to errors&lt;/span&gt;
  &lt;span class="c1"&gt;# ------------------------------------------------------------&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authentication_timeout&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;errors: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Authentication Timeout'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="mi"&gt;419&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;forbidden_resource&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;errors: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Not Authorized To Access Resource'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :forbidden&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;user_not_authenticated&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;errors: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Not Authenticated'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :unauthorized&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;Now, for any protected method, add &lt;code&gt;authenticate_request!&lt;/code&gt; to the beginning of the action method or in a before action filter.&lt;/p&gt;

&lt;h2 id="client-side"&gt;Client Side&lt;/h2&gt;

&lt;p&gt;Now let&amp;rsquo;s switch to the client side. First, we&amp;rsquo;ll create a module that wraps our authentication api request. Next, we&amp;rsquo;ll need to implement a way to store our session info so that our React components can access it. And finally we&amp;rsquo;ll create our login form component.&lt;/p&gt;

&lt;p&gt;Note that this will only cover the bare minimum of what you&amp;rsquo;ll probably need. Among topics that won&amp;rsquo;t be covered are persisting the session to local storage (so that they can come back later and still be logged in) and renewing the session when it expires.&lt;/p&gt;

&lt;p&gt;Also, note that I&amp;rsquo;m using ES6 (or ES2015, as some like to call it) in all of my javascript code, transpiled using &lt;a href="http://babeljs.io"&gt;babel&lt;/a&gt;. I&amp;rsquo;m a long-time Coffeescript user, but I highly recommend moving towards ES6. It brings many of Coffeescript&amp;rsquo;s great features, plus the community as a whole is migrating towards it very quickly.&lt;/p&gt;

&lt;h3 id="auth-api-wrapper"&gt;Auth API Wrapper&lt;/h3&gt;

&lt;p&gt;For my react apps, I use the &lt;a href="https://github.com/mzabriskie/axios"&gt;axios&lt;/a&gt; http library. But you can use any library you&amp;rsquo;d like. This is just a simple method that makes an HTTP Post request to the server-side endpoint we just created.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;auth_api.js:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authenticate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;AuthAPI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;login&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;password&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;username&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="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;errResp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;AuthAPI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="session-managment-using-flux"&gt;Session Managment using Flux&lt;/h3&gt;

&lt;p&gt;Before we implement our login form component, we need a way to maintain the state of our user session. The best way to do this is to implement the &lt;a href="https://facebook.github.io/flux/"&gt;Flux&lt;/a&gt; pattern. If you are new to the Flux pattern, you should read up on it first, but it is essentially a circular data flow that starts with your &lt;strong&gt;View&lt;/strong&gt;, which triggers various &lt;strong&gt;Actions&lt;/strong&gt;, which are responded to by your &lt;strong&gt;Stores&lt;/strong&gt; who then update the application state, to which your &lt;strong&gt;View&lt;/strong&gt; changes accordingly. And then this process repeats for each user action.&lt;/p&gt;

&lt;p&gt;For example, by clicking on our logout link component (the view), the logout action is triggered. Then the session store listens to this action and responds by clearing out the user and session info. Then the view, which is listening to changes on the session store, responds by hiding the logout link and showing the login link instead.&lt;/p&gt;

&lt;p&gt;There are a number of Flux implementations out there, but I&amp;rsquo;ll use &lt;a href="https://github.com/spoike/refluxjs"&gt;Reflux&lt;/a&gt; because it is simple and contains very little boilerplate code. So install it using NPM and then create two files: &lt;code&gt;auth_actions.js&lt;/code&gt; and &lt;code&gt;session_store.js&lt;/code&gt;. I think there&amp;rsquo;s some debate as to where data requests should originate within the flux architecture, but I&amp;rsquo;m going to go with Reflux&amp;rsquo;s suggestion of putting them in the Store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;auth_actions.js:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Reflux&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reflux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;AuthActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Reflux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createActions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// asyncResult creates 2 extra actions, one for success and one for failure&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loginRequest&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="na"&gt;asyncResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;logout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;AuthActions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;session_store.js:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Reflux&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reflux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AuthActions&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./auth_actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AuthAPI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./auth_api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This object is where we'll store all the session state.&lt;/span&gt;
&lt;span class="c1"&gt;// It will be a private variable and if any outside code&lt;/span&gt;
&lt;span class="c1"&gt;// wants to access it, they'll need to use one of the&lt;/span&gt;
&lt;span class="c1"&gt;// accessor methods below.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_sessionState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;authRequestInProgress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authErrors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Reflux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Map all the actions in AuthActions to the corresponding&lt;/span&gt;
  &lt;span class="c1"&gt;// methods below&lt;/span&gt;
  &lt;span class="na"&gt;listenables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthActions&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

  &lt;span class="c1"&gt;// When a login request occurs, use the AuthAPI to make&lt;/span&gt;
  &lt;span class="c1"&gt;// an api request to the server and call the appropriate&lt;/span&gt;
  &lt;span class="c1"&gt;// action when it finishes.&lt;/span&gt;
  &lt;span class="c1"&gt;// Trigger a change to alert subscribers about the fact&lt;/span&gt;
  &lt;span class="c1"&gt;// that a request is in progress.&lt;/span&gt;
  &lt;span class="nx"&gt;onLoginRequest&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;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authRequestInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;AuthAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&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;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// When a login request completes successfully,&lt;/span&gt;
  &lt;span class="c1"&gt;// set the user info to the session state object and&lt;/span&gt;
  &lt;span class="c1"&gt;// trigger a change&lt;/span&gt;
  &lt;span class="c1"&gt;// an api request to the server and call the appropriate&lt;/span&gt;
  &lt;span class="c1"&gt;// action method when it finishes.&lt;/span&gt;
  &lt;span class="nx"&gt;onLoginRequestCompleted&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authRequestInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authErrors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// You'll also need to redirect the user to the proper page,&lt;/span&gt;
    &lt;span class="c1"&gt;// but that's outside the scope of the article&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// When a login request fails, set the auth errors&lt;/span&gt;
  &lt;span class="c1"&gt;// and trigger a change&lt;/span&gt;
  &lt;span class="nx"&gt;onLoginRequestFailed&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authRequestInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authErrors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// When the user logs out, clear out the session state&lt;/span&gt;
  &lt;span class="c1"&gt;// and trigger a change&lt;/span&gt;
  &lt;span class="nx"&gt;onLogout&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;_sessionInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;authRequestInProgress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;authErrors&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// Accessor Methods&lt;/span&gt;
  &lt;span class="nx"&gt;getUsername&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;_sessionState&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="nx"&gt;getUserId&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;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;getAuthErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authErrors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;isAuthRequestInProgress&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authRequestInProgress&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="login-form-component"&gt;Login Form Component&lt;/h3&gt;

&lt;p&gt;Now we need a simple login form component. Upon submission, it will trigger the &lt;strong&gt;loginRequest&lt;/strong&gt; auth action, passing along the captured username and password.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AuthActions&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./auth_actions.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./session_store.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;LoginForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClass&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;handleLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refs&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;getDOMNode&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDOMNode&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;AuthActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&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;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;renderAuthErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAuthErrors&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;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AuthErrors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;))&lt;/span&gt;&lt;span class="sr"&gt; }&amp;lt;/u&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;buttonText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAuthRequestInProgress&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Submitting...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleLogin&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderAuthErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;SessionStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAuthRequestInProgress&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;LoginForm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let&amp;rsquo;s create a &amp;ldquo;UserControls&amp;rdquo; component that, when logged in, will show the user&amp;rsquo;s username and a link to logout. Otherwise, it will show a link to the login page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./session_store.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AuthActions&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./auth_actions.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;UserControls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClass&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;handleLogout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;AuthActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SessionStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UserControls&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;SessionStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUsername&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleLogout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Logout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="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="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UserControls&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserControls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we need to configure Axios with a request &amp;ldquo;interceptor&amp;rdquo; so that it includes our auth token in the &amp;lsquo;Authorization&amp;rsquo; header of every subsequent API request. This token is extracted and verified by our server so it knows the identity of the user. You&amp;rsquo;ll want to call this code as soon as your client app is initialized.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./session_store.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;SessionStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAuthToken&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;config&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;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As I said above, there are still some pieces missing that are outside the scope of this article, but this should at least get you started towards a nice auth experience in your Rails / React application. This code was somewhat roughly extracted from an existing codebase, so if you find any problems, let me know &lt;a href="https://twitter.com/adam_albrecht"&gt;on twitter&lt;/a&gt;. Thanks!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How to Replace the Angular Stack with React plus a few NPM modules</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2015/07/17/how-to-replace-the-angular-stack-with-the-react-ecosystem/"/>
    <id>https://www.adamalbrecht.com/blog/2015/07/17/how-to-replace-the-angular-stack-with-the-react-ecosystem/</id>
    <published>2015-07-17T00:00:00+00:00</published>
    <updated>2015-07-17T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;As you can tell from the content of my blog posts, I&amp;rsquo;ve been practicing and preaching Angular.js for quite some time now. It is an extremely productive web framework that felt like a big step forward from my days doing jQuery &amp;ldquo;sprinkles&amp;rdquo; and then Backbone.&lt;/p&gt;

&lt;p&gt;But then recently, I started playing with Facebook&amp;rsquo;s &lt;a href="https://facebook.github.io/react/"&gt;React&lt;/a&gt; framework. And while I&amp;rsquo;m still not quite as productive as I was with Angular, I absolutely love the code that I&amp;rsquo;m writing. And on top of that, it has opened my eyes to a whole new paradigm for creating user interfaces.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I won&amp;rsquo;t make this an article comparing and contrasting the libraries (a google search will probably turn up dozens of these), but here are the main reasons I&amp;rsquo;ve made the switch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small API surface area - you can learn 90% of React in 1 day (unlike Angular, where &lt;a href="feelings_about_angularjs_over_time.png"&gt;this is the common learning experience&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Due to the efficiency of the virtual DOM, you don&amp;rsquo;t have to worry about updating the DOM. You just write a single &lt;code&gt;render()&lt;/code&gt; function that is run over and over and applied in an efficient manner. It makes writing your views more similar to how you&amp;rsquo;d write them on the server because your view is simply a reflection of your current state. Angular&amp;rsquo;s 2-way binding is nice, but it comes at a cost of speed and complexity.&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;Everything is a component&amp;rdquo; paradigm is an extremely pleasant and simple way to create user interfaces.&lt;/li&gt;
&lt;li&gt;Everything is just javascript. Even the &amp;ldquo;templates&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And I&amp;rsquo;m sure there are others. Angular is still a great framework, but at the end of the day, I enjoy writing code in React quite a bit more. And interestingly enough, while I had previously been under the impression that React was a 1-trick pony that you used when performance was a big requirement, the fact that it&amp;rsquo;s extremely fast probably wouldn&amp;rsquo;t make the top 10 reasons why I would pick it over other frameworks.&lt;/p&gt;

&lt;p&gt;One of the biggest differences between the two libraries is their scope (and this can be both good and bad). React only provides the view layer, while Angular provides quite a bit more, such as libraries for promises, http, dependency injection, etc, etc.&lt;/p&gt;

&lt;p&gt;So how do we replace all these concepts in the React world? Let&amp;rsquo;s go over them one by one.&lt;/p&gt;

&lt;h2 id="routing"&gt;Routing&lt;/h2&gt;

&lt;p&gt;Angular has a new router that I hear is great, but all my experience had been with &lt;a href="https://github.com/angular-ui/ui-router"&gt;UI-Router&lt;/a&gt;, which I generally liked. There is a React-focused router called &lt;a href="https://github.com/rackt/react-router"&gt;react-router&lt;/a&gt; that is really fantastic. It is highly inspired by Ember&amp;rsquo;s built-in router, but uses React&amp;rsquo;s JSX syntax to structure your routes.&lt;/p&gt;

&lt;h2 id="promises"&gt;Promises&lt;/h2&gt;

&lt;p&gt;Promises are in most JS apps these days and ES6 (the next version of Javascript) will have built-in promises, but until then, we will need to use a library. Angular includes the very nice &lt;a href="#"&gt;$q&lt;/a&gt; library that, as of version 1.3, uses a syntax fairly similar to that of ES6. For a non-Angular project, we have a few choices. First, there is &lt;a href="https://github.com/jakearchibald/es6-promise"&gt;es6-promise&lt;/a&gt;, which is a polyfill that just includes the exact functionality that ES6 will have. But there was one feature that I missed from $q, which was the &lt;code&gt;finally()&lt;/code&gt; method. So if you need this feature, I recommend the &lt;a href="https://github.com/petkaantonov/bluebird"&gt;Bluebird&lt;/a&gt; library.&lt;/p&gt;

&lt;h2 id="http-requests"&gt;HTTP Requests&lt;/h2&gt;

&lt;p&gt;For my early Angular projects, I used &lt;a href="https://github.com/mgonto/restangular"&gt;Restangular&lt;/a&gt;, but in later projects, I found myself just using &lt;a href="https://docs.angularjs.org/api/ng/service/$http"&gt;$http&lt;/a&gt; with a service for each resource. &lt;a href="https://github.com/mzabriskie/axios"&gt;Axios&lt;/a&gt; is a library that is very similar to (and, in fact, inspired by) $http. Like $http, it is promise-based, automatically transforms JSON, and allows you to setup request and response interceptors.&lt;/p&gt;

&lt;h2 id="modules-dependency-injection"&gt;Modules / Dependency Injection&lt;/h2&gt;

&lt;p&gt;Angular includes its own dependency injection framework for importing other libraries. It has a quirky syntax, but it generally works pretty well. But it is Angular-only, so it can be a bit awkward to pull in 3rd party libraries that weren&amp;rsquo;t built for Angular. In React, you can just use NPM modules, which are widely supported, by using a bundling library such as &lt;a href="http://webpack.github.io/"&gt;WebPack&lt;/a&gt; or &lt;a href="http://browserify.org/"&gt;Browserify&lt;/a&gt; (I suggest Webpack). Then you can just require other modules like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;otherLib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some-other-library&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="unit-testing-mocking"&gt;Unit Testing &amp;amp; Mocking&lt;/h2&gt;

&lt;p&gt;Easy unit testing is one of my favorite things about Angular, so it&amp;rsquo;s great to know that their test runner, &lt;a href="http://karma-runner.github.io/0.13/index.html"&gt;Karma&lt;/a&gt;, isn&amp;rsquo;t specific to angular and can just as easily be used with React.&lt;/p&gt;

&lt;p&gt;Facebook actually has their own test runner and flavor of Jasmine called &lt;a href="https://facebook.github.io/jest/"&gt;Jest&lt;/a&gt;, which has two things going for it: It&amp;rsquo;s easy to setup and it auto-mocks your dependencies by default. But I found it to be painfully slow and quickly switched to &lt;a href="http://mochajs.org/"&gt;Mocha&lt;/a&gt; plus &lt;a href="http://chaijs.com/"&gt;Chai&lt;/a&gt; and running tests using &lt;a href="http://karma-runner.github.io/0.13/index.html"&gt;Karma&lt;/a&gt;. And there are a few testing helper libraries included in React that can be used with any framework.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;When I first moved from server-generated &amp;ldquo;traditional&amp;rdquo; web apps (and some light backbone apps) over to Angular, it felt like a huge step forward. While moving to React may not be as big of a step in terms of productivity, it feels like a huge move forward in terms of code simplicity and cleanliness. I&amp;rsquo;m officially a convert, and I highly suggest that you check it out. And now that you know the basics of the React ecosystem, there&amp;rsquo;s no excuse not to give it a try.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Authenticating your Angular / Rails App with JSON Web Tokens</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2014/12/04/add-json-web-token-authentication-to-your-angular-rails-app/"/>
    <id>https://www.adamalbrecht.com/blog/2014/12/04/add-json-web-token-authentication-to-your-angular-rails-app/</id>
    <published>2014-12-04T00:00:00+00:00</published>
    <updated>2014-12-04T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;&lt;em&gt;UPDATE: There have been some changes in the JWT Gem that make some of the below not work exactly right (it&amp;rsquo;ll still be about 90% the same). Specifically, they added expiration support. See &lt;a href="/2015/07/20/authentication-using-json-web-tokens-using-rails-and-react"&gt;my post on the same topic, but using React.js&lt;/a&gt;. The server side code in this post will work just as well with Angular.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m a big proponent of rolling your own authentication solution, especially if you&amp;rsquo;re only doing simple username/password based logins (as opposed to logging in via an OAuth provider). I&amp;rsquo;ve tried to use &lt;a href="https://github.com/plataformatec/devise"&gt;Devise&lt;/a&gt; on a number of Rails apps, but I always end up ripping it out. It&amp;rsquo;s not because Devise is a bad gem, but because it always takes me more time to customize it to my liking than it does to just write everything myself. And the flexibility of a custom solution almost always comes in handy down the road. I have generally implemented it the same way that Ryan Bates does in &lt;a href="http://railscasts.com/episodes/250-authentication-from-scratch-revised"&gt;this Railscasts episode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But now that most of my greenfield projects are single page javascript apps, authentication has become slightly more complicated. While you can certainly continue doing traditional authentication with cookies and server-rendered views, my preference is to use a token-based approach. This has a number of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The same authentication API can be used by all types of clients (web app, mobile app, etc).&lt;/li&gt;
&lt;li&gt;It is stateless, so the web server does not have to keep track of session information, which is good for scaling.&lt;/li&gt;
&lt;li&gt;Protected against CSRF (cross-site request forgery) attacks&lt;/li&gt;
&lt;li&gt;All of your views are rendered by the client, rather than a mix of server and client rendered views.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A relatively new standard for accomplishing this is &lt;a href="http://jwt.io/"&gt;JSON Web Tokens&lt;/a&gt; (abbreviated to JWT). I won&amp;rsquo;t dig into the details because there are plenty of good resources, but JWT is a way of digitally signing data to be transferred between two parties. The data is represented as an encoded JSON object. In a nutshell, these tokens are passed to the client upon successful authentication and then subsequently used in every HTTP request in order to verify the identity of the client.&lt;/p&gt;

&lt;p&gt;READMORE&lt;/p&gt;

&lt;h3 id="client-server-data-flow"&gt;Client/Server Data Flow&lt;/h3&gt;

&lt;p&gt;So the application flow will look something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client sends username and password to server.&lt;/li&gt;
&lt;li&gt;If credentials are valid, the server generates a token that include&amp;rsquo;s the user&amp;rsquo;s ID inside the token payload. (Remember, this payload is not encrypted - the client can read it - so don&amp;rsquo;t put anything you don&amp;rsquo;t want the client to see)&lt;/li&gt;
&lt;li&gt;The token is returned to the client, who saves it somewhere for later use.&lt;/li&gt;
&lt;li&gt;When the client makes a request for protected data from the server, it includes the token in an HTTP header.&lt;/li&gt;
&lt;li&gt;Upon receiving a request for protected data, the server looks at the token and verifies that it was indeed generated for the user represented by the ID in the payload.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="server-side-code"&gt;Server-Side Code&lt;/h2&gt;

&lt;p&gt;So let&amp;rsquo;s start with the server-side code and assume you already have a basic user model. We&amp;rsquo;ll first need some code to generate a JWT for a given user. So install the &lt;a href="https://github.com/progrium/ruby-jwt"&gt;jwt gem&lt;/a&gt; into your Gemfile. Next, I found there to be fair amount of logic around the JWT auth tokens, so I extracted it into a simple &lt;code&gt;AuthToken&lt;/code&gt; class that takes care of encoding and decoding the tokens for us.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthToken&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:exp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
  &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;DecodedAuthToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt;
    &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;# It will raise an error if it is not a token that was generated with our secret key or if the user changes the contents of the payload&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;# We could just return the payload as a hash, but having keys with indifferent access is always nice, plus we get an expired? method that will be useful later&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DecodedAuthToken&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;HashWithIndifferentAccess&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expired?&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:exp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&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 let&amp;rsquo;s add a helper method to our &lt;code&gt;User&lt;/code&gt; model that uses this class:&lt;/p&gt;
&lt;div class="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;generate_auth_token&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="no"&gt;AuthToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&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;Ok, now we need to take care of that initial authentication request in our Client/Server Data flow. The client sends a username/password combination and the server sends back a new token. So go ahead and create a new controller called &lt;code&gt;AuthController&lt;/code&gt; and add a new &lt;code&gt;post&lt;/code&gt; route to &lt;code&gt;routes.rb&lt;/code&gt;. You may also want to return some information about the current user inside the JSON response, but for now we&amp;rsquo;ll just return the auth token.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;skip_before_action&lt;/span&gt; &lt;span class="ss"&gt;:authenticate_request&lt;/span&gt; &lt;span class="c1"&gt;# this will be implemented later&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by_credentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# you'll need to implement this&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;auth_token: &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;generate_auth_token&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="s1"&gt;'Invalid username or password'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :unauthorized&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;# in routes.rb:&lt;/span&gt;
&lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'auth'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'auth#authenticate'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ok, now we need to add code to validate the token on subsequent requests. What we&amp;rsquo;ll do first is implement a few helper methods in our &lt;code&gt;ApplicationController&lt;/code&gt; that take care of decoding/validating the token and, based on the token payload, finding the current user. Then we&amp;rsquo;ll tie them all together in a a before filter/action. If the token is properly decoded and the user found, the request can be continued. If not, we&amp;rsquo;ll return a &lt;code&gt;401 Unauthorized&lt;/code&gt; response.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_current_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:authenticate_request&lt;/span&gt;

  &lt;span class="n"&gt;rescue_from&lt;/span&gt; &lt;span class="no"&gt;NotAuthenticatedError&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="s1"&gt;'Not Authorized'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :unauthorized&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;rescue_from&lt;/span&gt; &lt;span class="no"&gt;AuthenticationTimeoutError&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="s1"&gt;'Auth token is expired'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="mi"&gt;419&lt;/span&gt; &lt;span class="c1"&gt;# unofficial timeout status code&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="c1"&gt;# Based on the user_id inside the token payload, find the user.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_current_user&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decoded_auth_token&lt;/span&gt;
      &lt;span class="vi"&gt;@current_user&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded_auth_token&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&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;# Check to make sure the current user was set and the token is not expired&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate_request&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;auth_token_expired?&lt;/span&gt;
      &lt;span class="nb"&gt;fail&lt;/span&gt; &lt;span class="no"&gt;AuthenticationTimeoutError&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="vi"&gt;@current_user&lt;/span&gt;
      &lt;span class="nb"&gt;fail&lt;/span&gt; &lt;span class="no"&gt;NotAuthenticatedError&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;def&lt;/span&gt; &lt;span class="nf"&gt;decoded_auth_token&lt;/span&gt;
    &lt;span class="vi"&gt;@decoded_auth_token&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;AuthToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http_auth_header_content&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;auth_token_expired?&lt;/span&gt;
    &lt;span class="n"&gt;decoded_auth_token&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;decoded_auth_token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expired?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# JWT's are stored in the Authorization header using this format:&lt;/span&gt;
  &lt;span class="c1"&gt;# Bearer somerandomstring.encoded-payload.anotherrandomstring&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;http_auth_header_content&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="vi"&gt;@http_auth_header_content&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;defined?&lt;/span&gt; &lt;span class="vi"&gt;@http_auth_header_content&lt;/span&gt;
    &lt;span class="vi"&gt;@http_auth_header_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Authorization'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Authorization'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="kp"&gt;nil&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;ll also need to define the 2 errors that are being rescued from:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotAuthenticatedError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationTimeoutError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="client-side-code"&gt;Client Side Code&lt;/h2&gt;

&lt;p&gt;That should take care of the server side. Next, we&amp;rsquo;ll need to add support for these API&amp;rsquo;s into our angular app. To do this, we&amp;rsquo;ll need to implement two pieces of code: An AuthService that will handle logging in followed by an HTTP interceptor that will automatically attach our auth token to every http request and handle auth-related error responses.&lt;/p&gt;

&lt;p&gt;First, our AuthService. Note that there are two dependencies you&amp;rsquo;ll need to implement. First, &lt;code&gt;AuthToken&lt;/code&gt; is a simple service for storing the auth token in local storage while &lt;code&gt;AuthEvents&lt;/code&gt; is a constant with a few auth/login related events so we&amp;rsquo;re not using magic strings.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AuthService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AuthToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AuthEvents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&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;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/auth&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="na"&gt;username&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="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;AuthToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginSuccess&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&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="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginFailed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&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;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;You&amp;rsquo;ll need to implement a basic login form and controller that use this service.&lt;/p&gt;

&lt;p&gt;Next, let&amp;rsquo;s add our two http interceptors. The first is quite simple. Just attach &amp;ldquo;Bearer&amp;rdquo; followed by the auth token. This is the standard format for adding a JWT to your http headers. The error interceptor is slightly more complicatated. First, we check to make sure this isn&amp;rsquo;t our intial auth request because we want that to handle errors on its own. Then, we check to see if the response code matches any of our auth-related codes. If so, we broadcast an appropriate event.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AuthInterceptor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$injector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This will be called on every outgoing http request&lt;/span&gt;
    &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;AuthToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AuthToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AuthToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&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;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;token&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;config&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;$q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// This will be called on every incoming response that has en error status code&lt;/span&gt;
    &lt;span class="na"&gt;responseError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;AuthEvents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AuthEvents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;matchesAuthenticatePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/auth&lt;/span&gt;&lt;span class="dl"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;matchesAuthenticatePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$rootScope&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;$broadcast&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notAuthorized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="mi"&gt;419&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionTimeout&lt;/span&gt;
        &lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;response&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;$q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$httpProvider&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;$httpProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AuthInterceptor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Elsewhere....&lt;/span&gt;

&lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notAuthorized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... Take some action in response to a 401&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How you handle these auth error events will be up to you. The simplest solution is to just redirect the user to the login page. Or you may want to pop up a modal login form so that the user doesn&amp;rsquo;t lose his or her work.&lt;/p&gt;

&lt;p&gt;Also, this naively assumes you&amp;rsquo;ll have a long session length and the user won&amp;rsquo;t mind logging in again at the end, even if they&amp;rsquo;ve been actively using it the whole time. In my app, the session timeout length is just 60 minutes. So I implemented a timer that, every x minutes, requests to reissue the token (thus pushing back the expiration date) so long as there had been recent user activity. I may share this code in a future blog post, but I figured it was out of scope for the time being.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;d love to hear your feedback because, again, this was roughly extracted from my application and I&amp;rsquo;m not even sure it&amp;rsquo;s the best implementation. So let me know on twitter, where I&amp;rsquo;m &lt;a href="http://twitter.com/adam_albrecht"&gt;@adam_albrecht&lt;/a&gt;, if you find any bugs or ways to improve the code. Thanks!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Authorization with Angular.js and UI-Router</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2014/09/22/authorization-with-angular-and-ui-router/"/>
    <id>https://www.adamalbrecht.com/blog/2014/09/22/authorization-with-angular-and-ui-router/</id>
    <published>2014-09-22T00:00:00+00:00</published>
    <updated>2014-09-22T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;While working on an angular.js application recently, I found myself needing some form of authorization logic (not to be confused with authentication / login). I needed to restrict content in my app based on a user&amp;rsquo;s role as well as some other factors. At first, I created a single &lt;code&gt;AuthService&lt;/code&gt; service that dealt with login, authorization, and session management. But this felt messy and violated the &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;Single Responsibility Principle&lt;/a&gt;, so I decided to make something cleaner. My goal was for the API to look something like this:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;(Warning: lots of coffeescript ahead!)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;LoginService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCurrentUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# ... Elsewhere ....&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrentUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;authorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Authorizer&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;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;viewAdminSettings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# returns a boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By doing it this way, I was fairly sure I could split my formerly monolithic &lt;code&gt;AuthService&lt;/code&gt; into 3 separate services that had no dependencies on one another. I won&amp;rsquo;t go too detailed into the login and session services because they are fairly straight forward. &lt;code&gt;LoginService&lt;/code&gt; has one method that simply makes an HTTP request with a username and password and, if successful, returns the user object. &lt;code&gt;Session&lt;/code&gt; is a singleton service that, given a user, can create or destroy the current session. But my solution to Authorization was fairly interesting, so I thought I&amp;rsquo;d share.&lt;/p&gt;

&lt;p&gt;READMORE&lt;/p&gt;

&lt;p&gt;In the ruby world, I&amp;rsquo;ve used both &lt;a href="https://github.com/CanCanCommunity/cancancan"&gt;CanCan&lt;/a&gt; and &lt;a href="https://github.com/elabs/pundit"&gt;Pundit&lt;/a&gt; and so I drew a lot of inspiration from them. But at the same time, I was mindful that client-side authorization is never as complex as server side. You should never need to use client side authorization to filter data (that should be done server side), but only to show/hide pages and pieces of content.&lt;/p&gt;

&lt;p&gt;So first, I created a constant containing a set of permissions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;constant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'APP_PERMISSIONS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;viewAdminSettings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"viewAdminSettings"&lt;/span&gt;
  &lt;span class="na"&gt;editAdminSettings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"editAdminSettings"&lt;/span&gt;
  &lt;span class="na"&gt;viewLibrary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"viewLibrary"&lt;/span&gt;
  &lt;span class="na"&gt;editLibrary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"editLibrary"&lt;/span&gt;
  &lt;span class="na"&gt;viewBusinessAssociates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"viewBusinessAssociates"&lt;/span&gt;
  &lt;span class="na"&gt;editBusinessAssociates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"editBusinessAssociates"&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;ll notice that the keys and values are the same. I only made this an object rather than an array so I could refer to them with a dot syntax and wouldn&amp;rsquo;t have magic strings floating around.&lt;/p&gt;

&lt;p&gt;Next, as a good programmer does, I added a test for the &lt;code&gt;Authorizer&lt;/code&gt; service I was about to make.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt; &lt;span class="s"&gt;"Authorizer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;Authorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;null&lt;/span&gt;
  &lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;null&lt;/span&gt;

  &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'privacypro.auth'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_Authorizer_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_APP_PERMISSIONS_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;Authorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_Authorizer_&lt;/span&gt;
    &lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_APP_PERMISSIONS_&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="c1"&gt;# always add return statements to injection blocks in Coffeescript.&lt;/span&gt;
  &lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="nx"&gt;describe&lt;/span&gt; &lt;span class="s"&gt;"canAccess()"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;authorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;null&lt;/span&gt;
    &lt;span class="nx"&gt;describe&lt;/span&gt; &lt;span class="s"&gt;"An admin 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="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;beforeEach&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;authorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Authorizer&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;it&lt;/span&gt; &lt;span class="s"&gt;"can view the admin settings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;viewAdminSettings&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nx"&gt;describe&lt;/span&gt; &lt;span class="s"&gt;"A normal 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="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"normal"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;beforeEach&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;authorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Authorizer&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;it&lt;/span&gt; &lt;span class="s"&gt;"cannot view the admin settings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;viewAdminSettings&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;toBeFalsy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="s"&gt;"can view the library OR view the admin settings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;viewLibrary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;viewAdminSettings&lt;/span&gt;&lt;span class="p"&gt;])).&lt;/span&gt;&lt;span class="na"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="s"&gt;"throws an error if passed a bad permission"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;My specs included a number of examples and more complex scenarios, but you get the point. So next, I started work on my &lt;code&gt;Authorizer&lt;/code&gt; service. This class can be as simple or complex as your authorization requirements demand. In reality, my code is quite a bit more complex than below, but you&amp;rsquo;ll understand the basics from this example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorizer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;USER_ROLES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;return&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="na"&gt;canAccess&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;permissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nx"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;permission&lt;/span&gt; &lt;span class="o"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;permissions&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;"Bad permission value"&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;
            &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="nx"&gt;permission&lt;/span&gt;
              &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;viewAdminSettings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;editAdminSettings&lt;/span&gt;
                &lt;span class="k"&gt;return&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="na"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;USER_ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;editLibrary&lt;/span&gt;
                &lt;span class="k"&gt;return&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="na"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;USER_ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;USER_ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="c1"&gt;# etc...&lt;/span&gt;
          &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
        &lt;span class="no"&gt;false&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;Now I&amp;rsquo;m ready to add permissions to some of my routes. I always use &lt;a href="https://github.com/angular-ui/ui-router"&gt;UI-Router&lt;/a&gt;, but something similar can be done with &lt;a href="https://docs.angularjs.org/api/ngRoute/service/$route"&gt;ngRoute&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$stateProvider&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"..."&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;viewLibrary&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;APP_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;editAdminSettings&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;But how do I use this permission data and prevent a state from loading? To do this, you simply have to subscribe to ui-router&amp;rsquo;s &lt;code&gt;$stateChangeStart&lt;/code&gt; event and prevent it from propegating when necessary. Put this code inside of an angular run block.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Authorizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AUTH_EVENTS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;$on&lt;/span&gt; &lt;span class="s"&gt;"$stateChangeStart"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;permissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;permissions&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="no"&gt;null&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrentUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;authenticator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Authorizer&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="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;authenticator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;
        &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;$broadcast&lt;/span&gt; &lt;span class="nx"&gt;AUTH_EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notAuthenticated&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="nx"&gt;$rootScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;$broadcast&lt;/span&gt; &lt;span class="nx"&gt;AUTH_EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notAuthorized&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AUTH_EVENTS&lt;/code&gt; is another constant where I store various auth-related events.&lt;/li&gt;
&lt;li&gt;I did test this logic in my e2e tests via Protractor, but I don&amp;rsquo;t want to make this post too extremely long.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, I needed to restrict individual pieces of content on the page. One easy way to do this would be to create a helper method on the scope and use it in tandem with ngIf like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt; &lt;span class="na"&gt;ng-if=&lt;/span&gt;&lt;span class="s"&gt;"canAccess('editAdminSettings')"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Edit Admin Settings&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But this is a bit messy and I hate to pollute the scope unless absolutely necessary. So instead, I created a custom directive that will work similarly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt; &lt;span class="na"&gt;ng-if-permission=&lt;/span&gt;&lt;span class="s"&gt;"editAdminSettings"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Edit Admin Settings&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was hoping to simply extend the &lt;code&gt;ngIf&lt;/code&gt; directive with a specific set of logic, but I couldn&amp;rsquo;t find a way to do this (if you know how to do this, please let me know!). So instead, I simply copied &lt;a href="https://github.com/angular/angular.js/blob/master/src/ng/directive/ngIf.js"&gt;the ngIf source code&lt;/a&gt;, changed the name to &lt;code&gt;ngIfPermission&lt;/code&gt;, and made a few minor enhancements to the link function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;# the beginning is the same besides the name&lt;/span&gt;
&lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$transclude&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;undefined&lt;/span&gt;
  &lt;span class="nx"&gt;childScope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;undefined&lt;/span&gt;
  &lt;span class="nx"&gt;previousElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;undefined&lt;/span&gt;

  &lt;span class="c1"&gt;# There is no logic in the watch, so we can use $attr.$observe instead&lt;/span&gt;
  &lt;span class="nx"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;$observe&lt;/span&gt; &lt;span class="s"&gt;"ngIfPermission"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;# Check if we can access the permission(s)&lt;/span&gt;
    &lt;span class="nx"&gt;permissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrentUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;authenticator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Authorizer&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="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;authenticator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;childScope&lt;/span&gt;
        &lt;span class="nx"&gt;$transclude&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newScope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;childScope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newScope&lt;/span&gt;
          &lt;span class="c1"&gt;# change the contents of the placeholder comment&lt;/span&gt;
          &lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" end ngIfPermission: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ngIfPermission&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# the rest is the same&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So now we have a way to restrict access to pages as well as individual pieces of content. Remember, client side authorization is no substitute for proper server-side authorization. Anybody who is half-way decent with the Chrome dev tools can figure out how to manipulate your API requests.&lt;/p&gt;

&lt;p&gt;I hope this helps you in your journey to create a complex and full-featured angular app. If you have any questions or have a suggestion on how to improve the code, let me know on twitter, where I&amp;rsquo;m &lt;a href="http://twitter.com/adam_albrecht"&gt;@adam_albrecht&lt;/a&gt;. Thanks!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Building your Angular app with Gulp.js</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2014/06/20/building-your-angular-app-with-gulp-js/"/>
    <id>https://www.adamalbrecht.com/blog/2014/06/20/building-your-angular-app-with-gulp-js/</id>
    <published>2014-06-20T00:00:00+00:00</published>
    <updated>2014-06-20T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;As my work has transitioned from traditional web apps to thick-client Javascript apps (primarily using Angular), &lt;a href="http://gruntjs.com"&gt;Grunt&lt;/a&gt; has become essential in my workflow. Grunt is a nice tool and it gets the job done. But there was always something I didn&amp;rsquo;t like about it that I couldn&amp;rsquo;t quite articulate until I discovered &lt;a href="http://gulpjs.com"&gt;Gulp.js&lt;/a&gt;. Whereas in Grunt, you create a json configuration file, Gulp is just a script. It&amp;rsquo;s code. And it really fits my programmer brain better. In this post, I&amp;rsquo;ll convert a basic Gruntfile that compiles and minifies Coffeescript into Gulp.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3 id="the-original-gruntfile"&gt;The Original Gruntfile&lt;/h3&gt;

&lt;p&gt;The original Gulpfile I&amp;rsquo;m converting can be found &lt;a href="https://github.com/adamalbrecht/ngQuickDate/blob/48fb6f6db38de16d5c92bbbbe5e8e0eee2ad69b0/Gruntfile.js"&gt;here&lt;/a&gt;. It is for an angular datepicker library that I wrote called ngQuickDate. &lt;em&gt;(Side note: I&amp;rsquo;m in the middle of re-writing this library from the ground up because I no longer like the way it works)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I won&amp;rsquo;t put the entire file inline, but here are the relevant parts that compile coffeescript files and then minifies them.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;coffee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spec/build/specs.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spec/*.coffee&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist/ng-quick-date.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/*.coffee&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;uglify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;my_target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist/ng-quick-date.min.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist/ng-quick-date.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nx"&gt;grunt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadNpmTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;grunt-contrib-coffee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;grunt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadNpmTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;grunt-contrib-uglify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;grunt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coffee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uglify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s pretty straightforward, but I have 2 problems with it. First, my 2 tasks have no knowledge of one another. Coffeescript files are read, compiled, and written to disk. Then another task reads these new files in, minifies them, then writes to disk again. My second problem is that, with a configuration-based approach like this, it is very hard for a beginner to figure out how to modify tasks and add additional logic to them.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s first reproduce the same gruntfile in Gulp.&lt;/p&gt;

&lt;h3 id="simple-gulpfile"&gt;Simple Gulpfile&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;gulp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gulp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;concat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gulp-concat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gulp-coffee&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;uglify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gulp-uglify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;rename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gulp-rename&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/*.coffee&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;            &lt;span class="c1"&gt;// Read the files&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;coffee&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;bare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;               &lt;span class="c1"&gt;// Compile coffeescript&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng-quick-date.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;// Combine into 1 file&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;            &lt;span class="c1"&gt;// Write non-minified to disk&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uglify&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;                     &lt;span class="c1"&gt;// Minify&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.min.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt; &lt;span class="c1"&gt;// Rename to ng-quick-date.min.js&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;            &lt;span class="c1"&gt;// Write minified to disk&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While it&amp;rsquo;s not any shorter, I find it significantly easier to read and modify without referring to documenation. As you can see, Gulp accomplishes tasks by using streams and piping, which is a great fit for reading source files, performing a number of actions on them, then writing back out to disk. Each action is chained on to the last one and this makes it unecessary to write out to temp files, thus making it quite a bit faster, as well.&lt;/p&gt;

&lt;h3 id="angular-extras-in-gulp"&gt;Angular Extras in Gulp&lt;/h3&gt;

&lt;p&gt;If you&amp;rsquo;ve used Angular for any significant period of time, you&amp;rsquo;ll know that it&amp;rsquo;s a bit quirky. First, minification often breaks your app due to the way its dependency injection system works. But luckily there&amp;rsquo;s a fix for this: &lt;a href="https://github.com/btford/ngmin"&gt;ng-min&lt;/a&gt;. This library will analyze your source code and add the necessary arrays around function calls to make it minification friendly. For example, it will convert this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;whatever&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyCtrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;into&amp;hellip;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;whatever&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyCtrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$scope&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Integrating this into Grunt is easy enough, but you have to do so as an entirely separate task that runs independently of your compilation and minification. In gulp, we can add it into the middle of our chain of compilation/minification actions by adding a couple lines to our Gulpfile:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ngmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gulp-ngmin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NEW&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;coffee&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;bare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ngmin&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;                    &lt;span class="c1"&gt;// NEW: Make angular code friendly to minification&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng-quick-date.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Couldn&amp;rsquo;t be easier. Next, let&amp;rsquo;s say we&amp;rsquo;re also compiling html templates from Jade but we&amp;rsquo;d like them to pre-load them into Angular&amp;rsquo;s template cache so we don&amp;rsquo;t have to make http requests every time. No problem!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ngmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gulp-angular-templatecache&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/templates/*.jade&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="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jade&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;            &lt;span class="c1"&gt;// Compile from jade to html&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateCache&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;// Convert to JS strings and place in Angular template cache&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// Write the JS file to disk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But again, it&amp;rsquo;s easy to add steps in between. Next, let&amp;rsquo;s take care of the fact that Angular apps often produce html that is not valid html5. We can automatically add &lt;code&gt;data-&lt;/code&gt; prefixes to our various angular directive attributes by using the htmlify module:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;htmlify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gulp-angular-htmlify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateCache&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;htmlify&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;                &lt;span class="c1"&gt;// Add data- prefixes to non-html5-valid attributes&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, it&amp;rsquo;s fairly trivial to make changes to what started as an extremely basic gulp script.&lt;/p&gt;

&lt;p&gt;I wrote a couple angular starter templates that use gulp for compilation. One is meant for full web apps while the other is meant for creating angular libraries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/adamalbrecht/angular-starter-kit"&gt;angular-starter-kit&lt;/a&gt; - Build thick-client web apps. Be aware, this is pretty opinionated and won&amp;rsquo;t be for everyone.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/adamalbrecht/angular-lib-template"&gt;angular-lib-template&lt;/a&gt; - Build angular libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;hr&gt;&lt;/p&gt;

&lt;h3 id="more-resources"&gt;More Resources&lt;/h3&gt;

&lt;h3 id="documentation"&gt;Documentation:&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/gulpjs/gulp/blob/master/docs/README.md"&gt;Gulp.js Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="common-gulp-utilities"&gt;Common Gulp Utilities:&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wearefractal/gulp-concat"&gt;gulp-concat&lt;/a&gt; - Concatenate files&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gulpjs/gulp-util"&gt;gulp-util&lt;/a&gt; - Various gulp utility functions&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/peter-vilja/gulp-clean"&gt;gulp-clean&lt;/a&gt; - Clean out a folder before writing to disk&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nfroidure/StreamQueue"&gt;StreamQueue&lt;/a&gt; - Combine multiple streams into one while preserving the order&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/robrich/gulp-if"&gt;gulp-if&lt;/a&gt; - Apply actions to files that meet certain conditions&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hparra/gulp-rename"&gt;gulp-rename&lt;/a&gt; - Rename files&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mikaelbr/gulp-notify"&gt;gulp-notify&lt;/a&gt; - Show native OS notifications on compilation, errors, etc&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/avevlad/gulp-connect"&gt;gulp-connect&lt;/a&gt; - Mini web server for running your app&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="common-gulp-pre-processors"&gt;Common Gulp Pre-Processors&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wearefractal/gulp-coffee"&gt;gulp-coffee&lt;/a&gt; - Compile coffeescript&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sindresorhus/gulp-ruby-sass"&gt;gulp-ruby-sass&lt;/a&gt; - Compile (the ruby version of) sass and scss&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/plus3network/gulp-less"&gt;gulp-less&lt;/a&gt; - Compile less.css&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/phated/gulp-jade"&gt;gulp-jade&lt;/a&gt; - Compile jade templates&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sindresorhus/gulp-markdown"&gt;gulp-markdown&lt;/a&gt; - Compile markdown&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="minification-plugins"&gt;Minification Plugins&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/terinjokes/gulp-uglify"&gt;gulp-uglify&lt;/a&gt; - Minify / uglify code&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jonathanepollack/gulp-minify-html"&gt;gulp-minify-html&lt;/a&gt; - Minify html&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.org/package/gulp-minify-css"&gt;gulp-minify-css&lt;/a&gt; - Minify CSS&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sindresorhus/gulp-imagemin"&gt;gulp-imagemin&lt;/a&gt; - Compress images without losing quality&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="angular-helper-plugins"&gt;Angular Helper Plugins&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/btford/ngmin"&gt;gulp-ngmin&lt;/a&gt; - Make angular code friendly to minification&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pgilad/gulp-angular-htmlify"&gt;gulp-angular-htmlify&lt;/a&gt; - Make angular code valid html5&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Pre-Filling PDF Form Templates in Ruby-on-Rails with PDFtk</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2014/01/31/pre-filling-pdf-form-templates-in-ruby-on-rails-with-pdftk/"/>
    <id>https://www.adamalbrecht.com/blog/2014/01/31/pre-filling-pdf-form-templates-in-ruby-on-rails-with-pdftk/</id>
    <published>2014-01-31T00:00:00+00:00</published>
    <updated>2014-01-31T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;In &lt;a href="/2014/01/14/generate-clean-testable-pdf-reports-in-rails-with-prawn"&gt;a recent post&lt;/a&gt;, I talked about how to generate PDF reports in Rails using Prawn. This approach is great for generating PDF&amp;rsquo;s with lots of data tables and other variable-length content. But an alternative situation is when you already have a template authored in an application such as Adobe Acrobat and you want to populate it with data from your database. This makes it more difficult to insert variable-length content, but on the plus side, you no longer need to worry about the layout of the document.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;While there are a number of libraries out there that can perform PDF manipulation, the one I have found to work best is &lt;a href="http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/"&gt;PDFtk&lt;/a&gt;. There is a GUI version, but you&amp;rsquo;ll want the &lt;a href="http://www.pdflabs.com/tools/pdftk-server/"&gt;command line version&lt;/a&gt;, which is available in most package managers. &lt;sup id="fnref1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; This library is free for personal use, but requires a license if used in production.&lt;/p&gt;

&lt;p&gt;PDFtk is a non-ruby command line tool and while it works great on its own in that context, it will be much easier if we use a ruby wrapper, so go ahead and add the &lt;a href="https://github.com/jkraemer/pdf-forms"&gt;pdf-forms&lt;/a&gt; gem to your project.&lt;/p&gt;

&lt;p&gt;For this example, I&amp;rsquo;ve provided a really simple PDF form that I created in Adobe Acrobat &lt;sup id="fnref2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;. You can &lt;a href="/assets/other/test_form.pdf"&gt;download it here&lt;/a&gt; and add it to your project (I put mine in &lt;code&gt;lib/pdf_templates&lt;/code&gt;). There are plenty of other resources out there on creating PDF forms, so I won&amp;rsquo;t go over that, but make sure you take note of the names of the fields. If you are starting with a template created by someone else, you&amp;rsquo;ll still want to open it up in Adobe Acrobat (or a similar app) to reference the names of the form fields. &lt;sup id="fnref3"&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt;. The pdf-forms gem has a command for viewing the names, but I found that it didn&amp;rsquo;t always work.&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/images/adobe_acrobat_pdf_form-befc1ead.png" alt="Create your PDF form using Adobe Acrobat" /&gt;&lt;/p&gt;

&lt;p&gt;Next, let&amp;rsquo;s get to the coding. Just as in my post on generating pdfs with Prawn, I like to represent each pdf document as a ruby class. But first let&amp;rsquo;s create a base class that takes care of the common functionality. So create a file called fillable&lt;u&gt;pdf&lt;/u&gt;form.rb. In my rails app, I placed it in &lt;code&gt;app/pdfs&lt;/code&gt;. &lt;sup id="fnref4"&gt;&lt;a href="#fn4"&gt;4&lt;/a&gt;&lt;/sup&gt;. Here&amp;rsquo;s how my base class turned out:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FillablePdfForm&lt;/span&gt;

  &lt;span class="nb"&gt;attr_writer&lt;/span&gt; &lt;span class="ss"&gt;:template_path&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:attributes&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="n"&gt;fill_out&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;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_file_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;output_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output_file_path&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tmp/pdfs/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.pdf"&lt;/span&gt; &lt;span class="c1"&gt;# make sure tmp/pdfs exists&lt;/span&gt;
    &lt;span class="n"&gt;pdftk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill_form&lt;/span&gt; &lt;span class="n"&gt;template_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;
    &lt;span class="n"&gt;output_path&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;get_field_names&lt;/span&gt; 
    &lt;span class="n"&gt;pdftk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_field_names&lt;/span&gt; &lt;span class="n"&gt;template_path&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;template_path&lt;/span&gt;
    &lt;span class="vi"&gt;@template_path&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/lib/pdf_templates/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Pdf'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;underscore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.pdf"&lt;/span&gt; &lt;span class="c1"&gt;# makes assumption about template file path unless otherwise specified&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;protected&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;attributes&lt;/span&gt;
    &lt;span class="vi"&gt;@attributes&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&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;pdftk&lt;/span&gt;
    &lt;span class="vi"&gt;@pdftk&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;PdfForms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'PDFTK_PATH'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'/usr/local/bin/pdftk'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# On my Mac, the location of pdftk was different than on my linux server.&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;fill_out&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'Must be overridden by child class'&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 now I can keep my actual test pdf form class short and sweet. The &lt;code&gt;fill_out&lt;/code&gt; method is all that&amp;rsquo;s required.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestPdfForm&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;FillablePdfForm&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;protected&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fill_out&lt;/span&gt;
    &lt;span class="n"&gt;fill&lt;/span&gt; &lt;span class="ss"&gt;:date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:address_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:zip_code&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&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;field&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;fill&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&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="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;fill&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'0_17'&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'18_34'&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s1"&gt;'35_54'&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s1"&gt;'55_plus'&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;fill&lt;/span&gt; &lt;span class="ss"&gt;:comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Hello, World"&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 my controller might look something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pdf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;send_file&lt;/span&gt; &lt;span class="no"&gt;TestPdfForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;export&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: &lt;/span&gt;&lt;span class="s1"&gt;'application/pdf'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that&amp;rsquo;s all you need! The generated form will be both readable and writable in Adobe Reader and Mac Preview. So if you need the user to fill out a few additional fields, they can do so. But if you don&amp;rsquo;t want this, simply mark the fields in your template as read-only. So if your template isn&amp;rsquo;t a &amp;ldquo;form&amp;rdquo; but you just want to merge some data into a document, this is still a great way to do it.&lt;/p&gt;

&lt;p&gt;From there, creating additional forms is extremely easy. The only difficulty I ever encounter is in figuring out the proper field names for templates I didn&amp;rsquo;t create, but this is still fairly trivial.&lt;/p&gt;

&lt;p&gt;If you have any questions, send them to me on &lt;a href="http://twitter.com/adam_albrecht"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;div class="footnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;While PDFtk is free for personal use, it does require a license in production.&amp;nbsp;&lt;a href="#fnref1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;There are many lower-cost and free alternatives to Adobe Acrobat, but I don&amp;rsquo;t have any experience with them, so I won&amp;rsquo;t make any recommendations.&amp;nbsp;&lt;a href="#fnref2"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;If Acrobat shows you an error message that something like &amp;ldquo;This form cannot be edited in Acrobat. Please use Adobe LiveCycle Designer to edit this form&amp;rdquo;, then you&amp;rsquo;ll either need to either get a version of the PDF that doesn&amp;rsquo;t have these permissions turned on or you&amp;rsquo;ll need to export it the document as a new pdf, and then re-import it into Acrobat and lay out the form fields yourself.&amp;nbsp;&lt;a href="#fnref3"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;You may need to restart your dev server to make sure it picks up changes in this new folder.&amp;nbsp;&lt;a href="#fnref4"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  <entry>
    <title>A Better Onboarding Experience in your Angular.js Application</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2014/01/22/a-better-onboarding-experience-in-your-angular-js-application/"/>
    <id>https://www.adamalbrecht.com/blog/2014/01/22/a-better-onboarding-experience-in-your-angular-js-application/</id>
    <published>2014-01-22T00:00:00+00:00</published>
    <updated>2014-01-22T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;&amp;ldquo;Onboarding&amp;rdquo; is one of those things we sometimes forget about when developing an application, but it really deserves more attention. Showing the user how to use your app can be critical in retaining them. Some people might say that if you need onboarding, your app just needs to have a better UX, but I don&amp;rsquo;t think this is practical in all situations, particularly complex business applications.&lt;/p&gt;

&lt;p&gt;For my current Angular app, I wanted a nice way to point out and explain the various features of the application right after signup. I looked through a few javascript plugins such as &lt;a href="http://easelinc.github.io/tourist/"&gt;Tourist.js&lt;/a&gt;, &lt;a href="http://jeffpickhardt.com/guiders/"&gt;Guiders.js&lt;/a&gt;, and a few others, but none seemed to work well with angular, so I decided to write my own, which I&amp;rsquo;m calling &lt;a href="https://github.com/adamalbrecht/ngOnboarding"&gt;ngOnboarding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/images/ng_onboarding_screenshot-d1c682a2.png" alt="ngOnboarding" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The library consists of a directive (&lt;code&gt;&amp;lt;onboarding-popover&amp;gt;&lt;/code&gt;) that requires an array of &amp;lsquo;steps&amp;rsquo; to be setup in your controller. Each step represents a popover element that may optionally point to an element on the screeen. Your step configuration might look something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onboardingSteps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;centered&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome to my app!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Account Setup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;right&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the form for configuring your account.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;attachTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#account_form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bottom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, I had to make a design decisions that I don&amp;rsquo;t particularly like, which is forcing you to reference CSS selectors in the controller. This is generally frowned upon in Angular, but I don&amp;rsquo;t see a another way to support anchoring the popovers to elements on the page. If you can think of a better way to implement this, I&amp;rsquo;d love to hear it.&lt;/p&gt;

&lt;p&gt;While it&amp;rsquo;s still in development and not well-tested, it seems to work pretty well, so check it out!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Generate Clean, Testable PDF Reports in Ruby/Rails with Prawn</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2014/01/14/generate-clean-testable-pdf-reports-in-rails-with-prawn/"/>
    <id>https://www.adamalbrecht.com/blog/2014/01/14/generate-clean-testable-pdf-reports-in-rails-with-prawn/</id>
    <published>2014-01-14T00:00:00+00:00</published>
    <updated>2014-01-14T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;p&gt;I generally hate PDF&amp;rsquo;s. The file format is complex and designed to mimic physical paper documents, which really has little to do with the web. But unfortunately, PDF&amp;rsquo;s are still very common and often expected, particularly when working on businesses applications. I have a legacy ruby-on-rails application with a number of PDF reports and I recently took the time to refactor them in a clean and testable manner. Here&amp;rsquo;s how I went about that process:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3 id="the-report-requirements"&gt;The Report Requirements&lt;/h3&gt;

&lt;p&gt;&lt;img src='/assets/images/example_pdf_report.png' style='float:right; margin: 10px; margin-right:0;' /&gt;&lt;/p&gt;

&lt;p&gt;For my project, most of my PDF reports consisted of primarily large tables of data along with a few other random pieces of data and information. Here is a screenshot of one of the simpler ones:&lt;/p&gt;

&lt;h3 id="prawn"&gt;Prawn&lt;/h3&gt;

&lt;p&gt;The reports I&amp;rsquo;m working on have been done with the &lt;a href="http://prawn.majesticseacreature.com"&gt;Prawn library&lt;/a&gt; from the beginning. This is the only direct PDF generation ruby library that I&amp;rsquo;m aware of. The early days of Prawn were a bit shaky and it didn&amp;rsquo;t support a number of features you&amp;rsquo;d expect, but the more recent versions are quite robust. And their &lt;a href="http://prawn.majesticseacreature.com/manual.pdf"&gt;self-documenting manual&lt;/a&gt; is generated using the library itself and is quite useful.&lt;/p&gt;

&lt;h3 id="why-not-use-an-html-to-pdf-library"&gt;Why not use an HTML-to-PDF Library?&lt;/h3&gt;

&lt;p&gt;There are several libraries available that let you write your PDF&amp;rsquo;s in HTML and CSS, including &lt;a href="https://github.com/pdfkit/pdfkit"&gt;PDFKit&lt;/a&gt; and &lt;a href="https://github.com/mileszs/wicked_pdf"&gt;wicked_pdf&lt;/a&gt;. Both of these use &lt;a href="https://code.google.com/p/wkhtmltopdf/"&gt;wkhtmltopdf&lt;/a&gt; behind the scenes. While this may suit your needs, I found that creating reports in this manner made it more difficult to manage the layout of the document, particularly when there was more than a single page.&lt;/p&gt;

&lt;h3 id="keep-it-dry"&gt;Keep it Dry&lt;/h3&gt;

&lt;p&gt;The first thing I noticed was how much was shared between the reports. Each had either identical or very similar headers and footers, along with a number of often-repeated design paradigms that could be easily encapsulated into helper methods and constants. So I created a parent class that all my PDF reports would inherit from. It looked something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PdfReport&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Prawn&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Document&lt;/span&gt;

  &lt;span class="c1"&gt;# Often-Used Constants&lt;/span&gt;
  &lt;span class="no"&gt;TABLE_ROW_COLORS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"FFFFFF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"DDDDDD"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="no"&gt;TABLE_FONT_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;
  &lt;span class="no"&gt;TABLE_BORDER_STYLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:grid&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_prawn_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_prawn_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;font_size&lt;/span&gt; &lt;span class="mi"&gt;10&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;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/public/logo.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"My Organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;size: &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: :bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;align: :center&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
      &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;size: &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: :bold_italic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;align: :center&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;def&lt;/span&gt; &lt;span class="nf"&gt;footer&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ... More helpers&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="pdf-report-classes"&gt;PDF Report Classes&lt;/h3&gt;

&lt;p&gt;Then I built my actual reports, each of which is its own class that inherits from the above &lt;code&gt;PdfReport&lt;/code&gt;. I broke up each section of the pdf into its own private method in order to make the code easy to follow.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EventSummaryReportPdf&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PdfReport&lt;/span&gt;
  &lt;span class="no"&gt;TABLE_WIDTHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="no"&gt;TABLE_HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="vi"&gt;@events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;

    &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="s1"&gt;'Event Summary Report'&lt;/span&gt;
    &lt;span class="n"&gt;display_event_table&lt;/span&gt;
    &lt;span class="n"&gt;footer&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;display_event_table&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;table_data&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;text&lt;/span&gt; &lt;span class="s2"&gt;"No Events Found"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="n"&gt;table_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;headers: &lt;/span&gt;&lt;span class="no"&gt;TABLE_HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;column_widths: &lt;/span&gt;&lt;span class="no"&gt;TABLE_WIDTHS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;row_colors: &lt;/span&gt;&lt;span class="no"&gt;TABLE_ROW_COLORS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;font_size: &lt;/span&gt;&lt;span class="no"&gt;TABLE_FONT_SIZE&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;def&lt;/span&gt; &lt;span class="nf"&gt;table_data&lt;/span&gt;
    &lt;span class="vi"&gt;@table_data&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="vi"&gt;@events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%m/%d/%y"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;created_by&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;: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;This PDF report could then be generated by the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# events = [...]&lt;/span&gt;
&lt;span class="n"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EventSummaryReportPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render_file&lt;/span&gt; &lt;span class="s2"&gt;"/tmp/my_report.pdf"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="integration-with-rails"&gt;Integration with Rails&lt;/h3&gt;

&lt;p&gt;As Ryan Bates suggested in his &lt;a href="http://railscasts.com/episodes/153-pdfs-with-prawn-revised"&gt;excellent screencast&lt;/a&gt;, I created a separate &lt;code&gt;app/pdfs&lt;/code&gt; folder where I placed all my reports. Then in my controller, I would have the following action method:&lt;/p&gt;
&lt;div class="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;summary_report&lt;/span&gt;
  &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
  &lt;span class="n"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EventSummaryReportPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pdf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;send_data&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;filename: &lt;/span&gt;&lt;span class="s1"&gt;'summary_report.pdf'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: &lt;/span&gt;&lt;span class="s1"&gt;'application/pdf'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;disposition: &lt;/span&gt;&lt;span class="s1"&gt;'inline'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="testing"&gt;Testing&lt;/h3&gt;

&lt;p&gt;What&amp;rsquo;s great about this solution is how well it lends itself to testing. By using the &lt;a href="https://github.com/yob/pdf-reader"&gt;pdf-reader gem&lt;/a&gt;, we can convert the renderred PDF into a string and assert that the proper content is included. So a couple example tests (using Rspec) might look something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;EventSummaryReportPdf&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'Given an array containing a single event'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:events&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="ss"&gt;id: &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;name: &lt;/span&gt;&lt;span class="s2"&gt;"Company Meeting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;created_at: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ago&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;created_by: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;full_name: &lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'The rendered pdf content'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:pdf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;EventSummaryReportPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:pdf_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;PDF&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;page&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="nf"&gt;to_s&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'contains the name of the event'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_content&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="kp"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Company Meeting'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'contains the full name of the user'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_content&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="kp"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This makes the process of creating PDF documents &lt;em&gt;a little&lt;/em&gt; less painful. For those of you who are HTML and CSS wizards, be prepared to get really frustrated by how hard it is to lay out your documents in code. But just be mindful of anything that can be encapsulated into a helper method for usage later.&lt;/p&gt;

&lt;p&gt;This covers one type of PDF report generation that is often more appropriate for generating variable-length reports. In my next blog post, I&amp;rsquo;m going to go over the process of pre-filling PDF form documents with data from your application.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How to Create a Simple Modal Dialog Directive in Angular.js</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2013/12/12/creating-a-simple-modal-dialog-directive-in-angular-js/"/>
    <id>https://www.adamalbrecht.com/blog/2013/12/12/creating-a-simple-modal-dialog-directive-in-angular-js/</id>
    <published>2013-12-12T00:00:00+00:00</published>
    <updated>2013-12-12T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;h3 id="modals-are-easy"&gt;Modals are Easy&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;ve used a dozen or so modal / lightbox plugins over the years, almost exclusively jQuery-based. But you know what I didn&amp;rsquo;t realize until fairly recently? Modals are easy to build yourself from scratch. So let&amp;rsquo;s make one in the Angular fashion.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3 id="the-requirements"&gt;The Requirements&lt;/h3&gt;

&lt;p&gt;I want to be able to create a modal with the following HTML:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;modal-dialog&lt;/span&gt; &lt;span class="na"&gt;show=&lt;/span&gt;&lt;span class="s"&gt;'modalShown'&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;'750px'&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;'90%'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Modal Content Goes here&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/modal-dialog&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And I&amp;rsquo;d like it to have the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Toggle it by setting a single $scope variable to true or false (above, the variable is &lt;code&gt;modalShown&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Optionally specify the height and width as either a px or % value.&lt;/li&gt;
&lt;li&gt;Overlay the rest of the screen&lt;/li&gt;
&lt;li&gt;Close by either clicking an X in the corner or outside the dialog&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="the-directive-code"&gt;The Directive Code&lt;/h3&gt;

&lt;p&gt;This is a fairly simple directive, with a link function that&amp;rsquo;s only a few lines long. The &lt;code&gt;show: &amp;#39;=&amp;#39;&lt;/code&gt; in the isolated scope sets up a 2-way binding between the variable given to the &lt;code&gt;show&lt;/code&gt; attribute and the &lt;code&gt;show&lt;/code&gt; variable on our scope. Setting this to true or false will toggle our modal dialog. And we check for height and width attributes and, if set, give the modal dialog an inline style. Finally, the &lt;code&gt;hideModal()&lt;/code&gt; method simply sets the &lt;code&gt;show&lt;/code&gt; variable to false.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;modalDialog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;restrict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;E&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Replace with the template below&lt;/span&gt;
    &lt;span class="na"&gt;transclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// we want to insert custom content inside the directive&lt;/span&gt;
    &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dialogStyle&lt;/span&gt; &lt;span class="o"&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;attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dialogStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&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;attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dialogStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hideModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// See below&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;h3 id="the-template"&gt;The Template&lt;/h3&gt;

&lt;p&gt;The template is also fairly basic. Note that the &lt;code&gt;ng-transclude&lt;/code&gt; indicates where your modal content will go. And also note the use of &lt;code&gt;ng-style&lt;/code&gt;, which will translate a javascript object into an inline style.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'ng-modal'&lt;/span&gt; &lt;span class="na"&gt;ng-show=&lt;/span&gt;&lt;span class="s"&gt;'show'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'ng-modal-overlay'&lt;/span&gt; &lt;span class="na"&gt;ng-click=&lt;/span&gt;&lt;span class="s"&gt;'hideModal()'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'ng-modal-dialog'&lt;/span&gt; &lt;span class="na"&gt;ng-style=&lt;/span&gt;&lt;span class="s"&gt;'dialogStyle'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'ng-modal-close'&lt;/span&gt; &lt;span class="na"&gt;ng-click=&lt;/span&gt;&lt;span class="s"&gt;'hideModal()'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;X&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'ng-modal-dialog-content'&lt;/span&gt; &lt;span class="na"&gt;ng-transclude&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="the-css"&gt;The CSS&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;m not going to spend any time going over this, but I will say that the following will only work in modern browsers (specifically the translate function). If you need &amp;lt;= IE9 support, you&amp;rsquo;ll need center the dialog using a different method.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.ng-modal-overlay&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* A dark translucent div that covers the whole screen */&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;9999&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;#000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.ng-modal-dialog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* A centered div above the overlay with a box shadow. */&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Default */&lt;/span&gt;

  &lt;span class="c"&gt;/* Center the dialog */&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-moz-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.ng-modal-dialog-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.ng-modal-close&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'arial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;'sans-serif'&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;h3 id="triggering-the-modal"&gt;Triggering the Modal&lt;/h3&gt;

&lt;p&gt;Finally, to put it all together, you&amp;rsquo;ll need to add a small bit of code to your HTML and controller.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;ng-click=&lt;/span&gt;&lt;span class="s"&gt;'toggleModal()'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Open Modal Dialog&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;modal-dialog&lt;/span&gt; &lt;span class="na"&gt;show=&lt;/span&gt;&lt;span class="s"&gt;'modalShown'&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;'750px'&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;'60%'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Modal Content Goes here&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/modal-dialog&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyCtrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modalShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toggleModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modalShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modalShown&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;h3 id="all-together"&gt;All Together&lt;/h3&gt;

&lt;p&gt;And that&amp;rsquo;s it! I put all the code together in a demo &lt;a href="http://jsbin.com/aDuJIku/2"&gt;on JSBin&lt;/a&gt;. Check it out. And I&amp;rsquo;ve put a slightly more polished and configurable version of this directive up &lt;a href="http://github.com/adamalbrecht/ngModal"&gt;on Github&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>A Better Date Picker in Angular.js</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2013/12/01/better-date-time-picker-in-angular-js/"/>
    <id>https://www.adamalbrecht.com/blog/2013/12/01/better-date-time-picker-in-angular-js/</id>
    <published>2013-12-01T00:00:00+00:00</published>
    <updated>2013-12-01T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;h3 id="update-march-14th-2015"&gt;UPDATE (March 14th, 2015)&lt;/h3&gt;

&lt;p&gt;When I first wrote this library, I didn&amp;rsquo;t have a great understanding of the &lt;a href="https://docs.angularjs.org/api/ng/type/ngModel.NgModelController"&gt;ngModelController API&lt;/a&gt;, nor good directive design. So I wouldn&amp;rsquo;t recommend this library anymore. I started on a replacement library &lt;a href="https://github.com/adamalbrecht/angular-date-picker-polyfill"&gt;here&lt;/a&gt;, though it&amp;rsquo;s not quite ready for production use.&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;I wasn&amp;rsquo;t particularly happy with any of the datepicker directives out there for Angular.js, so I decided to build one myself. I did it out of a need on my current project but also because I wanted to learn the ins and outs of directives. You can find the library &lt;a href="https://github.com/adamalbrecht/ngQuickDate"&gt;on Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3 id="requirements"&gt;Requirements:&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Easy to use via the keyboard. I hate when I&amp;rsquo;m using a form-centric application and there&amp;rsquo;s one particular field that I can&amp;rsquo;t just tab through.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No dependencies (besides angular). Many of the existing datepicker directives are just jQuery widgets that are made to work with Angular. I wanted to build something from scrath in the &amp;ldquo;angular way&amp;rdquo;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Very configurable. If it&amp;rsquo;s not totally required, make it optional.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lightweight styling that can be easily overridden. Too many front-end libraries assume you&amp;rsquo;re using bootstrap or a particular icon font. I actually am using bootstrap for my project, but I don&amp;rsquo;t want it to be forced on anyone.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="the-end-result"&gt;The End Result:&lt;/h3&gt;

&lt;p&gt;After a few hours hacking here and there for a couple weeks, I have something fairly stable that I&amp;rsquo;m calling &lt;a href="https://github.com/adamalbrecht/ngQuickDate"&gt;ngQuickDate&lt;/a&gt;. It is built with Coffeescript, meets all my requirements, is fairly well tested using &lt;a href="http://pivotal.github.io/jasmine/"&gt;jasmine&lt;/a&gt;, and works pretty damn well if you ask me. Unfortunately, there were quite a few breaking changes in the recent 1.2 release of Angular, so currently it only works with 1.0.8. I&amp;rsquo;ll be releasing a 1.2 compatible version shortly.&lt;/p&gt;

&lt;h3 id="lessons-learned"&gt;Lessons Learned:&lt;/h3&gt;

&lt;p&gt;If you really want to understand the amazing directive system in Angular, building a datepicker or another similarly-complex UI widget is a great way to go about it. I had to go through a number of iterations before it felt right, but I learned a lot in the process. A few things to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Learn what&amp;rsquo;s already built into angular before you pull in any 3rd-party libraries. For example, I didn&amp;rsquo;t realize at first that I could use filters in my javascript code (as opposed to just in templates), so I was using another library to format dates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Take the time to provide some decent configuration for your directive. Angular provides a nice way to set the original default settings using a &lt;a href="http://docs.angularjs.org/api/AUTO.$provide#methods_provider"&gt;&amp;lsquo;provider&amp;rsquo;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make 3rd-party libraries optional by providing basic functionality without them, and extended functionality with them. In ngQuickDate, you can configure it to work with a library like &lt;a href="http://sugarjs.com"&gt;Sugar.js&lt;/a&gt; for enhanced date parsing, but it&amp;rsquo;s not required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;a href="http://smacss.com/"&gt;SMACSS&lt;/a&gt; or a similarly modular system for writing your directive&amp;rsquo;s CSS. By doing this, you&amp;rsquo;re much less likely to use conflicting class names, you&amp;rsquo;ll write more efficient CSS, and make it easier to re-style.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stick to the tools you know and love if it will help your project. I started out with the intention of doing it in plain Javascript and CSS so I wouldn&amp;rsquo;t turn off any developers out there unfamiliar with Coffeescript or any of the CSS pre-processors. But writing Coffeescript is just so much more fun the end-result is much more succinct and readable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>How to Auto-Save your model in Angular.js using $watch and a Debounce function.</title>
    <link rel="alternate" href="https://www.adamalbrecht.com/blog/2013/10/30/auto-save-your-model-in-angular-js-with-watch-and-debounce/"/>
    <id>https://www.adamalbrecht.com/blog/2013/10/30/auto-save-your-model-in-angular-js-with-watch-and-debounce/</id>
    <published>2013-10-30T00:00:00+00:00</published>
    <updated>2013-10-30T00:00:00+00:00</updated>
    <author name="Adam Albrecht"/>
    <content type="html">&lt;h3 id="the-problem"&gt;The Problem&lt;/h3&gt;

&lt;p&gt;Currently, I&amp;rsquo;m working on an Angular app that is very form-centric. Fields and fields and more fields. I want to make the form-filling process as quick and painless as possible, so I&amp;rsquo;m trying to implement auto-save.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;h3 id="update-march-19th-2014"&gt;Update (March 19th, 2014)&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;ve done quite a bit more auto-saving on my current project and I&amp;rsquo;ve updated my post with some slightly better methods. It also now has a solution for when you are trying to auto-save multiple items in an array. I combined a lot of the info below into &lt;a href="http://jsbin.com/xohugepe/1/edit?html,js,output"&gt;this live example&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;

&lt;h3 id="first-attempt"&gt;First Attempt&lt;/h3&gt;

&lt;p&gt;My first attempt at an auto-save solution (while still being very new to Angular) was a directive that, based on the type of element, waited for either a &lt;code&gt;change&lt;/code&gt; or &lt;code&gt;blur&lt;/code&gt; event to occur and communicated to the controller (via a service) that it was time to save the model.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text'&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field1'&lt;/span&gt; &lt;span class="na"&gt;auto-save&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field2'&lt;/span&gt; &lt;span class="na"&gt;auto-save&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A simpler version of this method might look something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text'&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field1'&lt;/span&gt; &lt;span class="na"&gt;ng-blur=&lt;/span&gt;&lt;span class="s"&gt;'save()'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field2'&lt;/span&gt; &lt;span class="na"&gt;ng-change=&lt;/span&gt;&lt;span class="s"&gt;'save()'&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are a few problems with this method:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I have to add these extra attributes to each and every input field. If I happen to forget one, my user may lose their data since there aren&amp;rsquo;t any explicit &amp;lsquo;Save&amp;rsquo; buttons.&lt;/li&gt;
&lt;li&gt;It won&amp;rsquo;t auto-save until the user changes the focus of the field. This is particularly problematic with &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; fields, where the user may type for long periods of time before changing focus.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;d much rather my view not know anything about when my model is or isn&amp;rsquo;t being saved to the server.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="new-solution-watch-and-debounce"&gt;New Solution: $watch and debounce&lt;/h3&gt;

&lt;p&gt;My new solution uses the &lt;code&gt;$watch&lt;/code&gt; method that Angular provides for watching for changes to scope variables. I don&amp;rsquo;t want to make requests to the server with every keystroke, so I&amp;rsquo;ll use a simple debounce function (using Angular&amp;rsquo;s &lt;code&gt;$timeout&lt;/code&gt; service) to limit my requests to happening every few seconds.&lt;/p&gt;

&lt;p&gt;To implement this solution, there is nothing to add to your view. But in the controller, you&amp;rsquo;ll need to inject &lt;code&gt;$timeout&lt;/code&gt; and write a couple &lt;code&gt;$watch&lt;/code&gt; statement. I added a watch statement for each individual attribute of the model, but you could also do a deep watch of the entire model. This is slightly more expensive performance-wise.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text'&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field1'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field2'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myCtrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;saveUpdates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// .... save data to server&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;debounceSaveUpdates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldVal&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;newVal&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;oldVal&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;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saveUpdates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 1000 = 1 second&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myModel.field1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;debounceSaveUpdates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myModel.field2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;debounceSaveUpdates&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;h3 id="potential-gotcha-1-validation"&gt;Potential Gotcha #1: Validation&lt;/h3&gt;

&lt;p&gt;Angular.js doesn&amp;rsquo;t provide any sort of model validation (or any model-related code at all) and instead recommends that you validate the form using a combination of HTML5 validation and a few built in directives. Angular includes a way to access our form and its &lt;code&gt;$valid&lt;/code&gt; attribute. First, we need to wrap our fields in a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; tag with a &lt;code&gt;name&lt;/code&gt; attribute and also make our fields required.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'myForm'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text'&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field1'&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;ng-model=&lt;/span&gt;&lt;span class="s"&gt;'myModel.field2'&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, we need to update our controller a bit to check the validity of our form.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;saveUpdates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&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;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// .... save data to server&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;If you need more complex validators, you&amp;rsquo;ll need to create custom directives that make use of the &lt;a href="http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController#methods_$setvalidity"&gt;$setValidity&lt;/a&gt; method.&lt;/p&gt;

&lt;h3 id="potential-gotcha-2-preventing-double-saves-on-create"&gt;Potential Gotcha #2: Preventing Double-Saves on Create&lt;/h3&gt;

&lt;p&gt;One problem I ran into was that when I auto-saved a brand new object was that the object was replaced with the version from the server, causing the &lt;code&gt;$watch&lt;/code&gt; function to be triggered again. The result was that my object was immediately saved a second time, unnecessarily. The solution to this is fairly simple: just set a &lt;code&gt;saveInProgress&lt;/code&gt; flag so that it never starts another save before the previous one finishes. This will also prevent a double-save caused by a save call that is slower than the timeout on your debounce function. It might look something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;saveInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;saveFinished&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;saveInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;saveUpdates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&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;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;saveInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;saveFunction&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saveFinished&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// The finally method runs regarless of whether the save was successful or not.&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;A related and much harder problem is how to resolve changes to the model that happen during the round-trip of the save. I recently &lt;a href="https://twitter.com/realtarnschaf/status/407489612227940352"&gt;had a discussion on Twitter about this&lt;/a&gt;, but I think it really comes down to designing your UX to discourage or prevent your user from making changes to the model while still waiting on that first &lt;code&gt;POST&lt;/code&gt; creation request. If you also replace your model with the server&amp;rsquo;s version on subsequent updates (which is generally not recommended), the problem gets a little trickier.&lt;/p&gt;

&lt;h3 id="potential-gotcha-3-auto-saving-individual-items-in-an-array"&gt;Potential Gotcha #3: Auto-Saving individual items in an array&lt;/h3&gt;

&lt;p&gt;Another issue that you&amp;rsquo;ll often run into is when you have an array of objects, perhaps in a grid interface. While angular does provide a &lt;code&gt;$watchCollection&lt;/code&gt; method, it only does a shallow watch on the array as a whole and won&amp;rsquo;t tell you which item was changed.&lt;/p&gt;

&lt;p&gt;Instead, a better solution is to wrap the fields of each individual item inside a child controller or directive. &lt;a href="http://jsbin.com/xohugepe/1/edit?html,js,output"&gt;Here is a live example of how that would work.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s it! This is an extremely simple example, so if you have any questions or comments, give me a shout out &lt;a href="http://twitter.com/adam_albrecht"&gt;on Twitter&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
</feed>
